@workflow/core 5.0.0-beta.3 → 5.0.0-beta.31

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 (268) hide show
  1. package/dist/attribute-changes.d.ts +7 -0
  2. package/dist/attribute-changes.d.ts.map +1 -0
  3. package/dist/attribute-changes.js +25 -0
  4. package/dist/capabilities.d.ts +22 -1
  5. package/dist/capabilities.d.ts.map +1 -1
  6. package/dist/capabilities.js +41 -4
  7. package/dist/capture-stack.d.ts +16 -0
  8. package/dist/capture-stack.d.ts.map +1 -0
  9. package/dist/capture-stack.js +21 -0
  10. package/dist/class-serialization.d.ts +32 -0
  11. package/dist/class-serialization.d.ts.map +1 -1
  12. package/dist/class-serialization.js +37 -1
  13. package/dist/classify-error.d.ts +26 -3
  14. package/dist/classify-error.d.ts.map +1 -1
  15. package/dist/classify-error.js +103 -6
  16. package/dist/context-errors.d.ts +27 -0
  17. package/dist/context-errors.d.ts.map +1 -0
  18. package/dist/context-errors.js +101 -0
  19. package/dist/context-violation-error.d.ts +97 -0
  20. package/dist/context-violation-error.d.ts.map +1 -0
  21. package/dist/context-violation-error.js +147 -0
  22. package/dist/create-hook.d.ts +42 -3
  23. package/dist/create-hook.d.ts.map +1 -1
  24. package/dist/create-hook.js +4 -3
  25. package/dist/define-hook.d.ts.map +1 -1
  26. package/dist/define-hook.js +20 -5
  27. package/dist/describe-error.d.ts +70 -0
  28. package/dist/describe-error.d.ts.map +1 -0
  29. package/dist/describe-error.js +165 -0
  30. package/dist/encryption.d.ts +22 -1
  31. package/dist/encryption.d.ts.map +1 -1
  32. package/dist/encryption.js +72 -27
  33. package/dist/events-consumer.d.ts +25 -1
  34. package/dist/events-consumer.d.ts.map +1 -1
  35. package/dist/events-consumer.js +95 -16
  36. package/dist/flushable-stream.d.ts +10 -10
  37. package/dist/flushable-stream.d.ts.map +1 -1
  38. package/dist/flushable-stream.js +26 -15
  39. package/dist/global.d.ts +35 -1
  40. package/dist/global.d.ts.map +1 -1
  41. package/dist/global.js +21 -3
  42. package/dist/index.d.ts +1 -0
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +2 -1
  45. package/dist/log-format.d.ts +25 -0
  46. package/dist/log-format.d.ts.map +1 -0
  47. package/dist/log-format.js +250 -0
  48. package/dist/logger.d.ts +29 -30
  49. package/dist/logger.d.ts.map +1 -1
  50. package/dist/logger.js +82 -32
  51. package/dist/private.d.ts +107 -2
  52. package/dist/private.d.ts.map +1 -1
  53. package/dist/private.js +80 -3
  54. package/dist/runtime/constants.d.ts +189 -0
  55. package/dist/runtime/constants.d.ts.map +1 -1
  56. package/dist/runtime/constants.js +310 -15
  57. package/dist/runtime/get-port-lazy.d.ts +25 -0
  58. package/dist/runtime/get-port-lazy.d.ts.map +1 -0
  59. package/dist/runtime/get-port-lazy.js +92 -0
  60. package/dist/runtime/get-world-lazy.d.ts +23 -0
  61. package/dist/runtime/get-world-lazy.d.ts.map +1 -0
  62. package/dist/runtime/get-world-lazy.js +46 -0
  63. package/dist/runtime/helpers.d.ts +57 -6
  64. package/dist/runtime/helpers.d.ts.map +1 -1
  65. package/dist/runtime/helpers.js +169 -32
  66. package/dist/runtime/replay-budget.d.ts +98 -0
  67. package/dist/runtime/replay-budget.d.ts.map +1 -0
  68. package/dist/runtime/replay-budget.js +192 -0
  69. package/dist/runtime/resume-hook.d.ts.map +1 -1
  70. package/dist/runtime/resume-hook.js +39 -23
  71. package/dist/runtime/run-id-time.d.ts +10 -0
  72. package/dist/runtime/run-id-time.d.ts.map +1 -0
  73. package/dist/runtime/run-id-time.js +31 -0
  74. package/dist/runtime/run.d.ts +6 -2
  75. package/dist/runtime/run.d.ts.map +1 -1
  76. package/dist/runtime/run.js +52 -10
  77. package/dist/runtime/runs.d.ts +36 -2
  78. package/dist/runtime/runs.d.ts.map +1 -1
  79. package/dist/runtime/runs.js +18 -7
  80. package/dist/runtime/start.d.ts +58 -1
  81. package/dist/runtime/start.d.ts.map +1 -1
  82. package/dist/runtime/start.js +160 -46
  83. package/dist/runtime/step-executor.d.ts +131 -0
  84. package/dist/runtime/step-executor.d.ts.map +1 -0
  85. package/dist/runtime/step-executor.js +818 -0
  86. package/dist/runtime/step-handler.d.ts.map +1 -1
  87. package/dist/runtime/step-handler.js +718 -557
  88. package/dist/runtime/step-latency.d.ts +131 -0
  89. package/dist/runtime/step-latency.d.ts.map +1 -0
  90. package/dist/runtime/step-latency.js +155 -0
  91. package/dist/runtime/step-ownership.d.ts +72 -0
  92. package/dist/runtime/step-ownership.d.ts.map +1 -0
  93. package/dist/runtime/step-ownership.js +114 -0
  94. package/dist/runtime/step-single-flight.d.ts +12 -0
  95. package/dist/runtime/step-single-flight.d.ts.map +1 -0
  96. package/dist/runtime/step-single-flight.js +69 -0
  97. package/dist/runtime/suspension-handler.d.ts +81 -7
  98. package/dist/runtime/suspension-handler.d.ts.map +1 -1
  99. package/dist/runtime/suspension-handler.js +355 -137
  100. package/dist/runtime/wait-continuation.d.ts +84 -0
  101. package/dist/runtime/wait-continuation.d.ts.map +1 -0
  102. package/dist/runtime/wait-continuation.js +105 -0
  103. package/dist/runtime/wait-until.d.ts +18 -0
  104. package/dist/runtime/wait-until.d.ts.map +1 -0
  105. package/dist/runtime/wait-until.js +42 -0
  106. package/dist/runtime/world-compatibility.d.ts +5 -0
  107. package/dist/runtime/world-compatibility.d.ts.map +1 -0
  108. package/dist/runtime/world-compatibility.js +12 -0
  109. package/dist/runtime/world-init.d.ts +50 -0
  110. package/dist/runtime/world-init.d.ts.map +1 -0
  111. package/dist/runtime/world-init.js +50 -0
  112. package/dist/runtime/world-target.d.ts +11 -0
  113. package/dist/runtime/world-target.d.ts.map +1 -0
  114. package/dist/runtime/world-target.js +15 -0
  115. package/dist/runtime/world.d.ts +21 -9
  116. package/dist/runtime/world.d.ts.map +1 -1
  117. package/dist/runtime/world.js +58 -83
  118. package/dist/runtime.d.ts +15 -10
  119. package/dist/runtime.d.ts.map +1 -1
  120. package/dist/runtime.js +1757 -326
  121. package/dist/schemas.d.ts +1 -1
  122. package/dist/schemas.d.ts.map +1 -1
  123. package/dist/schemas.js +1 -1
  124. package/dist/serialization/client.d.ts +17 -0
  125. package/dist/serialization/client.d.ts.map +1 -0
  126. package/dist/serialization/client.js +48 -0
  127. package/dist/serialization/codec-devalue.d.ts +14 -0
  128. package/dist/serialization/codec-devalue.d.ts.map +1 -0
  129. package/dist/serialization/codec-devalue.js +98 -0
  130. package/dist/serialization/codec.d.ts +106 -0
  131. package/dist/serialization/codec.d.ts.map +1 -0
  132. package/dist/serialization/codec.js +17 -0
  133. package/dist/serialization/compression.d.ts +104 -0
  134. package/dist/serialization/compression.d.ts.map +1 -0
  135. package/dist/serialization/compression.js +260 -0
  136. package/dist/serialization/encryption.d.ts +33 -0
  137. package/dist/serialization/encryption.d.ts.map +1 -0
  138. package/dist/serialization/encryption.js +70 -0
  139. package/dist/serialization/errors.d.ts +34 -0
  140. package/dist/serialization/errors.d.ts.map +1 -0
  141. package/dist/serialization/errors.js +59 -0
  142. package/dist/serialization/format.d.ts +60 -0
  143. package/dist/serialization/format.d.ts.map +1 -0
  144. package/dist/serialization/format.js +97 -0
  145. package/dist/serialization/index.d.ts +19 -0
  146. package/dist/serialization/index.d.ts.map +1 -0
  147. package/dist/serialization/index.js +22 -0
  148. package/dist/serialization/reducers/class.d.ts +11 -0
  149. package/dist/serialization/reducers/class.d.ts.map +1 -0
  150. package/dist/serialization/reducers/class.js +68 -0
  151. package/dist/serialization/reducers/common.d.ts +16 -0
  152. package/dist/serialization/reducers/common.d.ts.map +1 -0
  153. package/dist/serialization/reducers/common.js +417 -0
  154. package/dist/serialization/reducers/step-function.d.ts +35 -0
  155. package/dist/serialization/reducers/step-function.d.ts.map +1 -0
  156. package/dist/serialization/reducers/step-function.js +88 -0
  157. package/dist/serialization/step.d.ts +17 -0
  158. package/dist/serialization/step.d.ts.map +1 -0
  159. package/dist/serialization/step.js +48 -0
  160. package/dist/serialization/types.d.ts +253 -0
  161. package/dist/serialization/types.d.ts.map +1 -0
  162. package/dist/serialization/types.js +25 -0
  163. package/dist/serialization/workflow.d.ts +29 -0
  164. package/dist/serialization/workflow.d.ts.map +1 -0
  165. package/dist/serialization/workflow.js +54 -0
  166. package/dist/serialization-format.d.ts +16 -0
  167. package/dist/serialization-format.d.ts.map +1 -1
  168. package/dist/serialization-format.js +213 -50
  169. package/dist/serialization.d.ts +322 -214
  170. package/dist/serialization.d.ts.map +1 -1
  171. package/dist/serialization.js +1575 -664
  172. package/dist/set-attributes.d.ts +18 -0
  173. package/dist/set-attributes.d.ts.map +1 -0
  174. package/dist/set-attributes.js +61 -0
  175. package/dist/sleep.d.ts.map +1 -1
  176. package/dist/sleep.js +3 -2
  177. package/dist/source-map.d.ts +5 -0
  178. package/dist/source-map.d.ts.map +1 -1
  179. package/dist/source-map.js +102 -10
  180. package/dist/step/context-storage.d.ts +53 -0
  181. package/dist/step/context-storage.d.ts.map +1 -1
  182. package/dist/step/context-storage.js +1 -1
  183. package/dist/step/get-closure-vars.d.ts.map +1 -1
  184. package/dist/step/get-closure-vars.js +3 -2
  185. package/dist/step/get-step-metadata.d.ts.map +1 -1
  186. package/dist/step/get-step-metadata.js +3 -2
  187. package/dist/step/get-workflow-metadata.d.ts.map +1 -1
  188. package/dist/step/get-workflow-metadata.js +3 -2
  189. package/dist/step/writable-stream.d.ts.map +1 -1
  190. package/dist/step/writable-stream.js +58 -6
  191. package/dist/step-hydration-cache.d.ts +148 -0
  192. package/dist/step-hydration-cache.d.ts.map +1 -0
  193. package/dist/step-hydration-cache.js +171 -0
  194. package/dist/step.d.ts.map +1 -1
  195. package/dist/step.js +144 -25
  196. package/dist/symbols.d.ts +28 -0
  197. package/dist/symbols.d.ts.map +1 -1
  198. package/dist/symbols.js +29 -1
  199. package/dist/telemetry/semantic-conventions.d.ts +98 -2
  200. package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
  201. package/dist/telemetry/semantic-conventions.js +66 -1
  202. package/dist/telemetry.d.ts +68 -0
  203. package/dist/telemetry.d.ts.map +1 -1
  204. package/dist/telemetry.js +106 -4
  205. package/dist/types.d.ts +6 -0
  206. package/dist/types.d.ts.map +1 -1
  207. package/dist/types.js +23 -1
  208. package/dist/util.d.ts +16 -6
  209. package/dist/util.d.ts.map +1 -1
  210. package/dist/util.js +25 -16
  211. package/dist/version.d.ts +1 -1
  212. package/dist/version.d.ts.map +1 -1
  213. package/dist/version.js +2 -2
  214. package/dist/vm/index.d.ts.map +1 -1
  215. package/dist/vm/index.js +3 -2
  216. package/dist/vm/script-cache.d.ts +28 -0
  217. package/dist/vm/script-cache.d.ts.map +1 -0
  218. package/dist/vm/script-cache.js +140 -0
  219. package/dist/workflow/abort-controller.d.ts +65 -0
  220. package/dist/workflow/abort-controller.d.ts.map +1 -0
  221. package/dist/workflow/abort-controller.js +277 -0
  222. package/dist/workflow/attribute-dispatcher.d.ts +6 -0
  223. package/dist/workflow/attribute-dispatcher.d.ts.map +1 -0
  224. package/dist/workflow/attribute-dispatcher.js +48 -0
  225. package/dist/workflow/create-hook.d.ts.map +1 -1
  226. package/dist/workflow/create-hook.js +25 -3
  227. package/dist/workflow/define-hook.d.ts +1 -1
  228. package/dist/workflow/define-hook.d.ts.map +1 -1
  229. package/dist/workflow/define-hook.js +8 -4
  230. package/dist/workflow/get-workflow-metadata.d.ts.map +1 -1
  231. package/dist/workflow/get-workflow-metadata.js +14 -3
  232. package/dist/workflow/hook.d.ts.map +1 -1
  233. package/dist/workflow/hook.js +207 -33
  234. package/dist/workflow/index.d.ts +1 -0
  235. package/dist/workflow/index.d.ts.map +1 -1
  236. package/dist/workflow/index.js +5 -3
  237. package/dist/workflow/set-attributes.d.ts +77 -0
  238. package/dist/workflow/set-attributes.d.ts.map +1 -0
  239. package/dist/workflow/set-attributes.js +65 -0
  240. package/dist/workflow/sleep.d.ts.map +1 -1
  241. package/dist/workflow/sleep.js +45 -8
  242. package/dist/workflow/world-init-stub.d.ts +15 -0
  243. package/dist/workflow/world-init-stub.d.ts.map +1 -0
  244. package/dist/workflow/world-init-stub.js +15 -0
  245. package/dist/workflow.d.ts +17 -1
  246. package/dist/workflow.d.ts.map +1 -1
  247. package/dist/workflow.js +190 -56
  248. package/docs/api-reference/create-hook.mdx +38 -0
  249. package/docs/api-reference/create-webhook.mdx +1 -0
  250. package/docs/api-reference/fetch.mdx +5 -0
  251. package/docs/api-reference/index.mdx +3 -0
  252. package/docs/api-reference/set-attributes.mdx +65 -0
  253. package/docs/foundations/cancellation.mdx +459 -0
  254. package/docs/foundations/errors-and-retries.mdx +7 -3
  255. package/docs/foundations/hooks.mdx +29 -0
  256. package/docs/foundations/idempotency.mdx +236 -11
  257. package/docs/foundations/index.mdx +1 -23
  258. package/docs/foundations/meta.json +3 -1
  259. package/docs/foundations/serialization.mdx +77 -41
  260. package/docs/foundations/starting-workflows.mdx +5 -1
  261. package/docs/foundations/streaming.mdx +14 -23
  262. package/docs/foundations/versioning.mdx +263 -0
  263. package/docs/how-it-works/cancellation.mdx +287 -0
  264. package/docs/how-it-works/code-transform.mdx +2 -2
  265. package/docs/how-it-works/encryption.mdx +2 -2
  266. package/docs/how-it-works/event-sourcing.mdx +2 -2
  267. package/docs/how-it-works/meta.json +2 -1
  268. package/package.json +32 -11
@@ -1,128 +1,246 @@
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, RunExpiredError, WorkflowWorldError, } from '@workflow/errors';
2
+ import { AttributeValidationError, SPEC_VERSION_CURRENT, SPEC_VERSION_SUPPORTS_COMPRESSION, } from '@workflow/world';
4
3
  import { importKey } from '../encryption.js';
5
4
  import { runtimeLogger } from '../logger.js';
6
5
  import { dehydrateStepArguments } from '../serialization.js';
7
6
  import * as Attribute from '../telemetry/semantic-conventions.js';
8
- import { serializeTraceCarrier } from '../telemetry.js';
9
- import { queueMessage } from './helpers.js';
10
- /**
11
- * Extracts W3C trace context headers from a trace carrier for HTTP propagation.
12
- * Returns an object with `traceparent` and optionally `tracestate` headers.
13
- */
14
- function extractTraceHeaders(traceCarrier) {
15
- const headers = {};
16
- if (traceCarrier.traceparent) {
17
- headers.traceparent = traceCarrier.traceparent;
7
+ import { getAbortStreamIdFromToken } from '../util.js';
8
+ import { getMaxInlineSteps } from './constants.js';
9
+ async function createHookEvent({ world, runId, hookEvent, queueItem, requestId, }) {
10
+ try {
11
+ const result = await world.events.create(runId, hookEvent, {
12
+ requestId,
13
+ });
14
+ // Check if the world returned a hook_conflict event instead of hook_created.
15
+ // The hook_conflict event is stored in the event log and will be replayed
16
+ // on the next workflow invocation, causing the hook's promise to reject.
17
+ if (result.event?.eventType === 'hook_conflict') {
18
+ return {
19
+ hasHookConflict: true,
20
+ hasAwaitedHookCreation: false,
21
+ };
22
+ }
23
+ return {
24
+ hasHookConflict: false,
25
+ hasAwaitedHookCreation: queueItem.hasConflictAwaiter === true,
26
+ };
18
27
  }
19
- if (traceCarrier.tracestate) {
20
- headers.tracestate = traceCarrier.tracestate;
28
+ catch (err) {
29
+ if (EntityConflictError.is(err)) {
30
+ runtimeLogger.info('Hook already exists, continuing', {
31
+ workflowRunId: runId,
32
+ message: err.message,
33
+ });
34
+ return {
35
+ hasHookConflict: false,
36
+ hasAwaitedHookCreation: queueItem.hasConflictAwaiter === true,
37
+ };
38
+ }
39
+ if (RunExpiredError.is(err)) {
40
+ runtimeLogger.info('Workflow run already completed, skipping hook', {
41
+ workflowRunId: runId,
42
+ message: err.message,
43
+ });
44
+ return {
45
+ hasHookConflict: false,
46
+ hasAwaitedHookCreation: false,
47
+ };
48
+ }
49
+ throw err;
21
50
  }
22
- return headers;
23
51
  }
24
52
  /**
25
53
  * Handles a workflow suspension by processing all pending operations (hooks, steps, waits).
26
- * Uses an event-sourced architecture where entities (steps, hooks) are created atomically
27
- * with their corresponding events via events.create().
54
+ * Creates events for all operations but does NOT queue step messages — returns the pending
55
+ * steps so the caller can decide which to execute inline vs queue to background.
28
56
  *
29
57
  * Processing order:
30
58
  * 1. Hooks are processed first to prevent race conditions with webhook receivers
31
- * 2. Steps and waits are processed in parallel after hooks complete
59
+ * 2. Step events and wait events are created in parallel
32
60
  */
33
- export async function handleSuspension({ suspension, world, run, span, requestId, }) {
61
+ export async function handleSuspension({ suspension, world, run, span, requestId, runReadyBarrier, }) {
34
62
  const runId = run.runId;
35
- const workflowName = run.workflowName;
36
- const workflowStartedAt = run.startedAt ? +run.startedAt : Date.now();
63
+ // Turbo mode: hold every world write below until the backgrounded
64
+ // `run_started` has *settled*, so we never write a step/hook/wait event for a
65
+ // run that does not exist yet. A no-op outside turbo (barrier undefined) and
66
+ // on the pure inline hot path, which defers all steps and writes nothing.
67
+ // Awaiting the same (usually already-settled) promise more than once is cheap.
68
+ // A barrier rejection is swallowed for ordering only: if `run_started` truly
69
+ // failed the run does not exist, so the subsequent write surfaces the real
70
+ // error (run not found / gone) and the message redelivers.
71
+ const ensureRunReady = async () => {
72
+ if (runReadyBarrier) {
73
+ try {
74
+ await runReadyBarrier;
75
+ }
76
+ catch {
77
+ // intentional: ordering barrier only — see above.
78
+ }
79
+ }
80
+ };
37
81
  // Separate queue items by type
38
82
  const stepItems = suspension.steps.filter((item) => item.type === 'step');
39
83
  const allHookItems = suspension.steps.filter((item) => item.type === 'hook');
40
84
  const waitItems = suspension.steps.filter((item) => item.type === 'wait');
41
- // Split hooks by what actions they need
85
+ const attributeItems = suspension.steps.filter((item) => item.type === 'attribute');
42
86
  const hooksNeedingCreation = allHookItems.filter((item) => !item.hasCreatedEvent);
43
- // Hooks needing disposal: any disposed hook (including those needing creation first)
44
- // Hooks are created before disposal in the processing order below
45
- const hooksNeedingDisposal = allHookItems.filter((item) => item.disposed);
87
+ // Group hook items that need work by token, preserving queue-insertion
88
+ // (workflow code) order within each token. Operations on one token must
89
+ // apply in code order: a dispose() of an earlier hook releases the token
90
+ // before a later same-token hook's creation is validated — otherwise the
91
+ // new hook records a spurious hook_conflict against the run's own
92
+ // disposed hook — while a hook created and disposed within the same
93
+ // suspension is still created before it is disposed. Different tokens
94
+ // have no claim interaction, so token groups are processed in parallel.
95
+ const hookItemsByToken = new Map();
96
+ for (const item of allHookItems) {
97
+ if (item.hasCreatedEvent && !item.disposed) {
98
+ continue; // already committed and still live — nothing to do
99
+ }
100
+ const group = hookItemsByToken.get(item.token);
101
+ if (group) {
102
+ group.push(item);
103
+ }
104
+ else {
105
+ hookItemsByToken.set(item.token, [item]);
106
+ }
107
+ }
46
108
  // Resolve encryption key for this run
47
109
  const rawKey = await world.getEncryptionKeyForRun?.(run);
48
110
  const encryptionKey = rawKey ? await importKey(rawKey) : undefined;
49
- // Build hook_created events (World will atomically create hook entities)
50
- const hookEvents = await Promise.all(hooksNeedingCreation.map(async (queueItem) => {
51
- const hookMetadata = typeof queueItem.metadata === 'undefined'
52
- ? undefined
53
- : (await dehydrateStepArguments(queueItem.metadata, runId, encryptionKey, suspension.globalThis));
54
- return {
55
- eventType: 'hook_created',
111
+ // Gate payload compression on the run's specVersion: only runs marked
112
+ // as possibly containing compressed payloads (spec >= 5) get gzip data.
113
+ const compression = (run.specVersion ?? 0) >= SPEC_VERSION_SUPPORTS_COMPRESSION;
114
+ async function disposeHook(queueItem) {
115
+ const hookDisposedEvent = {
116
+ eventType: 'hook_disposed',
56
117
  specVersion: SPEC_VERSION_CURRENT,
57
118
  correlationId: queueItem.correlationId,
58
119
  eventData: {
59
120
  token: queueItem.token,
60
- metadata: hookMetadata,
61
- isWebhook: queueItem.isWebhook ?? false,
62
121
  },
63
122
  };
64
- }));
65
- // Process hooks first to prevent race conditions with webhook receivers
66
- // All hook creations run in parallel
67
- // Track any hook conflicts that occur - these will be handled by re-enqueueing the workflow
68
- let hasHookConflict = false;
69
- if (hookEvents.length > 0) {
70
- await Promise.all(hookEvents.map(async (hookEvent) => {
71
- try {
72
- const result = await world.events.create(runId, hookEvent, {
73
- requestId,
123
+ try {
124
+ await world.events.create(runId, hookDisposedEvent, { requestId });
125
+ }
126
+ catch (err) {
127
+ if (EntityConflictError.is(err)) {
128
+ // Hook was already disposed by a concurrent invocation — safe to skip
129
+ runtimeLogger.info('Hook already disposed, skipping duplicate disposal', {
130
+ workflowRunId: runId,
131
+ correlationId: queueItem.correlationId,
132
+ message: err.message,
74
133
  });
75
- // Check if the world returned a hook_conflict event instead of hook_created
76
- // The hook_conflict event is stored in the event log and will be replayed
77
- // on the next workflow invocation, causing the hook's promise to reject
78
- // Note: hook events always create an event (legacy runs throw, not return undefined)
79
- if (result.event.eventType === 'hook_conflict') {
80
- hasHookConflict = true;
81
- }
82
134
  }
83
- catch (err) {
84
- if (EntityConflictError.is(err) || RunExpiredError.is(err)) {
85
- runtimeLogger.info('Workflow run already completed, skipping hook', {
86
- workflowRunId: runId,
87
- message: err.message,
135
+ else if (RunExpiredError.is(err)) {
136
+ runtimeLogger.info('Workflow run already completed, skipping hook disposal', {
137
+ workflowRunId: runId,
138
+ correlationId: queueItem.correlationId,
139
+ message: err.message,
140
+ });
141
+ }
142
+ else if (HookNotFoundError.is(err)) {
143
+ // Hook may have already been disposed or never created
144
+ runtimeLogger.info('Hook not found for disposal, continuing', {
145
+ workflowRunId: runId,
146
+ correlationId: queueItem.correlationId,
147
+ message: err.message,
148
+ });
149
+ }
150
+ else {
151
+ throw err;
152
+ }
153
+ }
154
+ }
155
+ // Process hooks first to prevent race conditions with webhook receivers.
156
+ // Track any hook conflicts that occur — these are returned to the caller
157
+ // so the V2 handler can re-invoke immediately.
158
+ let hasHookConflict = false;
159
+ let hasAwaitedHookCreation = false;
160
+ let hookCreationMs = 0;
161
+ if (hookItemsByToken.size > 0) {
162
+ const hookPhaseStart = Date.now();
163
+ await ensureRunReady();
164
+ await Promise.all([...hookItemsByToken.values()].map(async (items) => {
165
+ for (const queueItem of items) {
166
+ let creationConflicted = false;
167
+ if (!queueItem.hasCreatedEvent) {
168
+ const hookMetadata = typeof queueItem.metadata === 'undefined'
169
+ ? undefined
170
+ : (await dehydrateStepArguments(queueItem.metadata, runId, encryptionKey, suspension.globalThis, false, compression));
171
+ const hookEvent = {
172
+ eventType: 'hook_created',
173
+ specVersion: SPEC_VERSION_CURRENT,
174
+ correlationId: queueItem.correlationId,
175
+ eventData: {
176
+ token: queueItem.token,
177
+ metadata: hookMetadata,
178
+ isWebhook: queueItem.isWebhook ?? false,
179
+ ...(queueItem.isSystem && { isSystem: true }),
180
+ },
181
+ };
182
+ const result = await createHookEvent({
183
+ world,
184
+ runId,
185
+ hookEvent,
186
+ queueItem,
187
+ requestId,
88
188
  });
189
+ hasHookConflict ||= result.hasHookConflict;
190
+ hasAwaitedHookCreation ||= result.hasAwaitedHookCreation;
191
+ creationConflicted = result.hasHookConflict;
89
192
  }
90
- else {
91
- throw err;
193
+ // Dispose after creation for hooks born and disposed within this
194
+ // batch. A hook whose creation conflicted was never created, so
195
+ // there is nothing to dispose.
196
+ if (queueItem.disposed && !creationConflicted) {
197
+ await disposeHook(queueItem);
92
198
  }
93
199
  }
94
200
  }));
201
+ hookCreationMs = Date.now() - hookPhaseStart;
95
202
  }
96
- // Process hook disposals - these release hook tokens for reuse by other workflows
97
- if (hooksNeedingDisposal.length > 0) {
98
- await Promise.all(hooksNeedingDisposal.map(async (queueItem) => {
99
- const hookDisposedEvent = {
100
- eventType: 'hook_disposed',
101
- specVersion: SPEC_VERSION_CURRENT,
102
- correlationId: queueItem.correlationId,
103
- };
203
+ // Process abort requests resume the hook with abort payload and write stream packet
204
+ const hooksNeedingAbort = allHookItems.filter((item) => item.abortRequested && !item.disposed);
205
+ if (hooksNeedingAbort.length > 0) {
206
+ await ensureRunReady();
207
+ await Promise.all(hooksNeedingAbort.map(async (queueItem) => {
104
208
  try {
105
- await world.events.create(runId, hookDisposedEvent, { requestId });
106
- }
107
- catch (err) {
108
- if (EntityConflictError.is(err)) {
109
- // Hook was already disposed by a concurrent invocation — safe to skip
110
- runtimeLogger.info('Hook already disposed, skipping duplicate disposal', {
111
- workflowRunId: runId,
112
- correlationId: queueItem.correlationId,
113
- message: err.message,
114
- });
209
+ // Dehydrate the abort payload for storage
210
+ const abortPayload = await dehydrateStepArguments({ aborted: true, reason: queueItem.abortReason }, runId, encryptionKey, suspension.globalThis, false, compression);
211
+ // Create hook_received event with abort payload
212
+ await world.events.create(runId, {
213
+ eventType: 'hook_received',
214
+ specVersion: SPEC_VERSION_CURRENT,
215
+ correlationId: queueItem.correlationId,
216
+ eventData: {
217
+ token: queueItem.token,
218
+ payload: abortPayload,
219
+ },
220
+ });
221
+ // Write stream cancellation packet for real-time step propagation.
222
+ // Reuse the same dehydrated payload as the hook event so the reason
223
+ // round-trips through `dehydrateStepArguments` / `hydrateStepArguments`
224
+ // (handles DOMException, custom errors, encryption, etc.) instead of
225
+ // bare JSON.stringify which loses type information and drops undefined.
226
+ // streamName is set on the queue item at controller construction time
227
+ // (see workflow/abort-controller.ts).
228
+ try {
229
+ const streamName = getAbortStreamIdFromToken(queueItem.token);
230
+ await world.streams.write(runId, streamName, abortPayload);
231
+ await world.streams.close(runId, streamName);
115
232
  }
116
- else if (RunExpiredError.is(err)) {
117
- runtimeLogger.info('Workflow run already completed, skipping hook disposal', {
233
+ catch {
234
+ // Best-effort stream write hook event provides the durable fallback
235
+ runtimeLogger.debug('Failed to write abort stream packet, hook event will provide fallback', {
118
236
  workflowRunId: runId,
119
237
  correlationId: queueItem.correlationId,
120
- message: err.message,
121
238
  });
122
239
  }
123
- else if (HookNotFoundError.is(err)) {
124
- // Hook may have already been disposed or never created
125
- runtimeLogger.info('Hook not found for disposal, continuing', {
240
+ }
241
+ catch (err) {
242
+ if (EntityConflictError.is(err) || RunExpiredError.is(err)) {
243
+ runtimeLogger.info('Workflow run already completed, skipping abort', {
126
244
  workflowRunId: runId,
127
245
  correlationId: queueItem.correlationId,
128
246
  message: err.message,
@@ -134,35 +252,76 @@ export async function handleSuspension({ suspension, world, run, span, requestId
134
252
  }
135
253
  }));
136
254
  }
137
- // Build a map of stepId -> step event for steps that need creation
255
+ // Create step events for steps that don't have them yet.
256
+ // Unlike V1, we do NOT queue step messages from here — the caller
257
+ // decides which steps to execute inline vs. queue to background.
258
+ // Wait events are also created in parallel below.
138
259
  const stepsNeedingCreation = new Set(stepItems
139
260
  .filter((queueItem) => !queueItem.hasCreatedEvent)
140
261
  .map((queueItem) => queueItem.correlationId));
141
- // Process steps and waits in parallel
142
- // Each step: create event (if needed) -> queue message
143
- // Each wait: create event (if needed)
262
+ // Correlation IDs for which THIS suspension call actually wrote the
263
+ // step_created event. Populated by the ops below after a successful
264
+ // events.create used by the caller to claim ownership and avoid
265
+ // racing with concurrent handlers on step execution.
266
+ const createdStepCorrelationIds = new Set();
267
+ // Lazy inline start: defer the step_created write for up to
268
+ // `getMaxInlineSteps()` steps the caller will run inline (in parallel). Each
269
+ // step is created on the fly by the lazy `step_started` executeStep sends
270
+ // (saving a round-trip per step). We never defer when a `hook.getConflict()`
271
+ // awaiter is present, because in that case the caller executes nothing inline
272
+ // (it re-invokes immediately to resolve the awaiter), so deferring would
273
+ // leave the steps uncreated and unqueued. We pick the first N uncreated steps
274
+ // — matching the caller's inline-candidate selection — and dehydrate their
275
+ // input here so executeStep can ship it as the step_started payload.
276
+ const lazyInlineCorrelationIds = new Set(hasAwaitedHookCreation === false
277
+ ? stepItems
278
+ .filter((item) => stepsNeedingCreation.has(item.correlationId))
279
+ .slice(0, getMaxInlineSteps())
280
+ .map((item) => item.correlationId)
281
+ : []);
282
+ // Collected by correlationId because the per-step ops below run concurrently
283
+ // and settle out of order. We rebuild the array in deterministic
284
+ // `lazyInlineCorrelationIds` order (the ordered slice above) after the ops
285
+ // settle, so the inline batch order is stable regardless of dehydration timing.
286
+ const lazyInlineByCorrelationId = new Map();
144
287
  const ops = [];
145
- // Steps: create event then queue message, all in parallel
288
+ // Steps: create step_created events (no queuing V2 returns pending steps to caller)
146
289
  for (const queueItem of stepItems) {
147
- ops.push((async () => {
148
- // Create step event if not already created
149
- if (stepsNeedingCreation.has(queueItem.correlationId)) {
290
+ if (stepsNeedingCreation.has(queueItem.correlationId)) {
291
+ ops.push((async () => {
150
292
  const dehydratedInput = await dehydrateStepArguments({
151
293
  args: queueItem.args,
152
294
  closureVars: queueItem.closureVars,
153
295
  thisVal: queueItem.thisVal,
154
- }, runId, encryptionKey, suspension.globalThis);
296
+ }, runId, encryptionKey, suspension.globalThis, false, compression);
297
+ // Deferred (lazy) inline step: skip the step_created write — the
298
+ // caller's inline executeStep will send a lazy step_started carrying
299
+ // this input, and the world creates the step (entity + synthetic
300
+ // step_created event) atomically. We do NOT add it to
301
+ // createdStepCorrelationIds; ownership is decided by that lazy
302
+ // step_started's atomic create-claim instead.
303
+ if (lazyInlineCorrelationIds.has(queueItem.correlationId)) {
304
+ lazyInlineByCorrelationId.set(queueItem.correlationId, {
305
+ correlationId: queueItem.correlationId,
306
+ stepName: queueItem.stepName,
307
+ dehydratedInput: dehydratedInput,
308
+ });
309
+ return;
310
+ }
155
311
  const stepEvent = {
156
312
  eventType: 'step_created',
157
313
  specVersion: SPEC_VERSION_CURRENT,
158
314
  correlationId: queueItem.correlationId,
159
315
  eventData: {
160
316
  stepName: queueItem.stepName,
317
+ workflowName: run.workflowName,
161
318
  input: dehydratedInput,
162
319
  },
163
320
  };
164
321
  try {
322
+ await ensureRunReady();
165
323
  await world.events.create(runId, stepEvent, { requestId });
324
+ createdStepCorrelationIds.add(queueItem.correlationId);
166
325
  }
167
326
  catch (err) {
168
327
  if (EntityConflictError.is(err)) {
@@ -176,28 +335,10 @@ export async function handleSuspension({ suspension, world, run, span, requestId
176
335
  throw err;
177
336
  }
178
337
  }
179
- }
180
- // Queue step execution message
181
- // Serialize trace context once and include in both payload and headers
182
- // Payload: for manual context restoration in step handler
183
- // Headers: for automatic trace propagation by Vercel's infrastructure
184
- const traceCarrier = await serializeTraceCarrier();
185
- await queueMessage(world, `__wkf_step_${queueItem.stepName}`, {
186
- workflowName,
187
- workflowRunId: runId,
188
- workflowStartedAt,
189
- stepId: queueItem.correlationId,
190
- traceCarrier,
191
- requestedAt: new Date(),
192
- }, {
193
- idempotencyKey: queueItem.correlationId,
194
- headers: {
195
- ...extractTraceHeaders(traceCarrier),
196
- },
197
- });
198
- })());
338
+ })());
339
+ }
199
340
  }
200
- // Waits: create events in parallel (no queueing needed for waits)
341
+ // Create wait events (same as V1)
201
342
  for (const queueItem of waitItems) {
202
343
  if (!queueItem.hasCreatedEvent) {
203
344
  ops.push((async () => {
@@ -210,6 +351,7 @@ export async function handleSuspension({ suspension, world, run, span, requestId
210
351
  },
211
352
  };
212
353
  try {
354
+ await ensureRunReady();
213
355
  await world.events.create(runId, waitEvent, { requestId });
214
356
  }
215
357
  catch (err) {
@@ -227,40 +369,116 @@ export async function handleSuspension({ suspension, world, run, span, requestId
227
369
  })());
228
370
  }
229
371
  }
230
- // Wait for all step and wait operations to complete
231
- waitUntil(Promise.all(ops).catch((opErr) => {
232
- const isAbortError = opErr?.name === 'AbortError' || opErr?.name === 'ResponseAborted';
233
- if (!isAbortError)
234
- throw opErr;
235
- }));
372
+ for (const queueItem of attributeItems) {
373
+ ops.push((async () => {
374
+ try {
375
+ await ensureRunReady();
376
+ await world.events.create(runId, {
377
+ eventType: 'attr_set',
378
+ specVersion: SPEC_VERSION_CURRENT,
379
+ correlationId: queueItem.correlationId,
380
+ eventData: {
381
+ changes: queueItem.changes,
382
+ writer: { type: 'workflow' },
383
+ ...(queueItem.allowReservedAttributes
384
+ ? { allowReservedAttributes: true }
385
+ : {}),
386
+ },
387
+ }, { requestId });
388
+ }
389
+ catch (err) {
390
+ if (EntityConflictError.is(err)) {
391
+ runtimeLogger.info('Workflow attribute event already exists, continuing', {
392
+ workflowRunId: runId,
393
+ correlationId: queueItem.correlationId,
394
+ message: err.message,
395
+ });
396
+ }
397
+ else if (isAttributeValidationFailure(err)) {
398
+ // Deterministic validation rejection from the World — e.g. the
399
+ // cumulative per-run attribute cap, which only the World can
400
+ // check against the run's existing attributes. Redelivering the
401
+ // orchestrator message replays the workflow into the exact same
402
+ // write and the exact same rejection, so retrying can never
403
+ // succeed. Surface it as a FatalError so the caller fails the
404
+ // run with a clear error instead of wedging it in redelivery.
405
+ const fatal = new FatalError(`setAttributes failed World validation: ${err instanceof Error ? err.message : String(err)}`);
406
+ fatal.cause = err;
407
+ throw fatal;
408
+ }
409
+ else {
410
+ throw err;
411
+ }
412
+ }
413
+ })());
414
+ }
415
+ // Await the step_created / wait_created event creates before returning.
416
+ // The caller (workflowEntrypoint) only enqueues the step-dispatch queue
417
+ // messages AFTER handleSuspension resolves, and the queue handler acks
418
+ // the orchestrator message only after the caller resolves. So the step_created
419
+ // events must be durable here, and the dispatch sends must complete in the caller,
420
+ // all before ack. If the process crashes before this resolves, the orchestrator
421
+ // message is not acked and VQS redelivers, re-creates the (idempotent)
422
+ // step_created and re-dispatches, and recovers the run instead of orphaning it.
236
423
  await Promise.all(ops);
237
- // Calculate minimum timeout from waits
424
+ // Rebuild the inline batch in deterministic order. `lazyInlineCorrelationIds`
425
+ // is a Set seeded from the ordered first-N slice, so iterating it preserves
426
+ // stepItems order; every id in it was set by the lazy branch above.
427
+ const lazyInlineSteps = [];
428
+ for (const correlationId of lazyInlineCorrelationIds) {
429
+ const lazyStep = lazyInlineByCorrelationId.get(correlationId);
430
+ if (lazyStep)
431
+ lazyInlineSteps.push(lazyStep);
432
+ }
433
+ // Find the soonest pending wait (minimum timeout)
238
434
  const now = Date.now();
239
- const minTimeoutSeconds = waitItems.reduce((min, queueItem) => {
435
+ let soonestWait;
436
+ for (const queueItem of waitItems) {
240
437
  const resumeAtMs = queueItem.resumeAt.getTime();
241
438
  const delayMs = Math.max(1000, resumeAtMs - now);
242
439
  const timeoutSeconds = Math.ceil(delayMs / 1000);
243
- if (min === null)
244
- return timeoutSeconds;
245
- return Math.min(min, timeoutSeconds);
246
- }, null);
440
+ if (!soonestWait || timeoutSeconds < soonestWait.seconds) {
441
+ soonestWait = {
442
+ seconds: timeoutSeconds,
443
+ correlationId: queueItem.correlationId,
444
+ };
445
+ }
446
+ }
247
447
  span?.setAttributes({
248
448
  ...Attribute.WorkflowRunStatus('workflow_suspended'),
249
449
  ...Attribute.WorkflowStepsCreated(stepItems.length),
250
450
  ...Attribute.WorkflowHooksCreated(hooksNeedingCreation.length),
251
451
  ...Attribute.WorkflowWaitsCreated(waitItems.length),
252
452
  });
253
- // If any hook conflicts occurred, re-enqueue the workflow immediately
254
- // On the next iteration, the hook consumer will see the hook_conflict event
255
- // and reject the promise with a WorkflowRuntimeError
256
- // We do this after processing all other operations (steps, waits) to ensure
257
- // they are recorded in the event log before the re-execution
258
- if (hasHookConflict) {
259
- return { timeoutSeconds: 0 };
260
- }
261
- if (minTimeoutSeconds !== null) {
262
- return { timeoutSeconds: minTimeoutSeconds };
453
+ return {
454
+ pendingSteps: stepItems,
455
+ createdStepCorrelationIds,
456
+ lazyInlineSteps,
457
+ // On hook conflict the caller re-invokes immediately and never reads
458
+ // the wait timeout, so don't report one.
459
+ waitTimeout: hasHookConflict ? undefined : soonestWait,
460
+ hasHookConflict,
461
+ hasAwaitedHookCreation,
462
+ hasAttributeEvents: attributeItems.length > 0,
463
+ hasHookEvents: hooksNeedingCreation.length > 0,
464
+ hookCreationMs,
465
+ };
466
+ }
467
+ /**
468
+ * Whether an `events.create` rejection is a deterministic attribute
469
+ * validation failure rather than a transient/storage error. Local Worlds
470
+ * (world-local, world-postgres) throw `AttributeValidationError` directly;
471
+ * remote Worlds surface the equivalent server-side rejection as a
472
+ * `WorkflowWorldError` with HTTP status 400. The name check covers
473
+ * `AttributeValidationError` instances from a different copy of
474
+ * `@workflow/world` than the one this package resolved.
475
+ */
476
+ function isAttributeValidationFailure(err) {
477
+ if (err instanceof AttributeValidationError)
478
+ return true;
479
+ if (err instanceof Error && err.name === 'AttributeValidationError') {
480
+ return true;
263
481
  }
264
- return {};
482
+ return WorkflowWorldError.is(err) && err.status === 400;
265
483
  }
266
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3VzcGVuc2lvbi1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bnRpbWUvc3VzcGVuc2lvbi1oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUM5QyxPQUFPLEVBQ0wsbUJBQW1CLEVBQ25CLGlCQUFpQixFQUNqQixlQUFlLEdBQ2hCLE1BQU0sa0JBQWtCLENBQUM7QUFDMUIsT0FBTyxFQUdMLG9CQUFvQixHQUdyQixNQUFNLGlCQUFpQixDQUFDO0FBQ3pCLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQU83QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzdDLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzdELE9BQU8sS0FBSyxTQUFTLE1BQU0sc0NBQXNDLENBQUM7QUFDbEUsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDeEQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUU1Qzs7O0dBR0c7QUFDSCxTQUFTLG1CQUFtQixDQUMxQixZQUFvQztJQUVwQyxNQUFNLE9BQU8sR0FBMkIsRUFBRSxDQUFDO0lBQzNDLElBQUksWUFBWSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQzdCLE9BQU8sQ0FBQyxXQUFXLEdBQUcsWUFBWSxDQUFDLFdBQVcsQ0FBQztJQUNqRCxDQUFDO0lBQ0QsSUFBSSxZQUFZLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDNUIsT0FBTyxDQUFDLFVBQVUsR0FBRyxZQUFZLENBQUMsVUFBVSxDQUFDO0lBQy9DLENBQUM7SUFDRCxPQUFPLE9BQU8sQ0FBQztBQUNqQixDQUFDO0FBY0Q7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLGdCQUFnQixDQUFDLEVBQ3JDLFVB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aW1wb3J0IHsgd2FpdFVudGlsIH0gZnJvbSAnQHZlcmNlbC9mdW5jdGlvbnMnO1xuaW1wb3J0IHtcbiAgRW50aXR5Q29uZmxpY3RFcnJvcixcbiAgSG9va05vdEZvdW5kRXJyb3IsXG4gIFJ1bkV4cGlyZWRFcnJvcixcbn0gZnJvbSAnQHdvcmtmbG93L2Vycm9ycyc7XG5pbXBvcnQge1xuICB0eXBlIENyZWF0ZUV2ZW50UmVxdWVzdCxcbiAgdHlwZSBTZXJpYWxpemVkRGF0YSxcbiAgU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gIHR5cGUgV29ya2Zsb3dSdW4sXG4gIHR5cGUgV29ybGQsXG59IGZyb20gJ0B3b3JrZmxvdy93b3JsZCc7XG5pbXBvcnQgeyBpbXBvcnRLZXkgfSBmcm9tICcuLi9lbmNyeXB0aW9uLmpzJztcbmltcG9ydCB0eXBlIHtcbiAgSG9va0ludm9jYXRpb25RdWV1ZUl0ZW0sXG4gIFN0ZXBJbnZvY2F0aW9uUXVldWVJdGVtLFxuICBXYWl0SW52b2NhdGlvblF1ZXVlSXRlbSxcbiAgV29ya2Zsb3dTdXNwZW5zaW9uLFxufSBmcm9tICcuLi9nbG9iYWwuanMnO1xuaW1wb3J0IHsgcnVudGltZUxvZ2dlciB9IGZyb20gJy4uL2xvZ2dlci5qcyc7XG5pbXBvcnQgeyBkZWh5ZHJhdGVTdGVwQXJndW1lbnRzIH0gZnJvbSAnLi4vc2VyaWFsaXphdGlvbi5qcyc7XG5pbXBvcnQgKiBhcyBBdHRyaWJ1dGUgZnJvbSAnLi4vdGVsZW1ldHJ5L3NlbWFudGljLWNvbnZlbnRpb25zLmpzJztcbmltcG9ydCB7IHNlcmlhbGl6ZVRyYWNlQ2FycmllciB9IGZyb20gJy4uL3RlbGVtZXRyeS5qcyc7XG5pbXBvcnQgeyBxdWV1ZU1lc3NhZ2UgfSBmcm9tICcuL2hlbHBlcnMuanMnO1xuXG4vKipcbiAqIEV4dHJhY3RzIFczQyB0cmFjZSBjb250ZXh0IGhlYWRlcnMgZnJvbSBhIHRyYWNlIGNhcnJpZXIgZm9yIEhUVFAgcHJvcGFnYXRpb24uXG4gKiBSZXR1cm5zIGFuIG9iamVjdCB3aXRoIGB0cmFjZXBhcmVudGAgYW5kIG9wdGlvbmFsbHkgYHRyYWNlc3RhdGVgIGhlYWRlcnMuXG4gKi9cbmZ1bmN0aW9uIGV4dHJhY3RUcmFjZUhlYWRlcnMoXG4gIHRyYWNlQ2FycmllcjogUmVjb3JkPHN0cmluZywgc3RyaW5nPlxuKTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB7XG4gIGNvbnN0IGhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgaWYgKHRyYWNlQ2Fycmllci50cmFjZXBhcmVudCkge1xuICAgIGhlYWRlcnMudHJhY2VwYXJlbnQgPSB0cmFjZUNhcnJpZXIudHJhY2VwYXJlbnQ7XG4gIH1cbiAgaWYgKHRyYWNlQ2Fycmllci50cmFjZXN0YXRlKSB7XG4gICAgaGVhZGVycy50cmFjZXN0YXRlID0gdHJhY2VDYXJyaWVyLnRyYWNlc3RhdGU7XG4gIH1cbiAgcmV0dXJuIGhlYWRlcnM7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3VzcGVuc2lvbkhhbmRsZXJQYXJhbXMge1xuICBzdXNwZW5zaW9uOiBXb3JrZmxvd1N1c3BlbnNpb247XG4gIHdvcmxkOiBXb3JsZDtcbiAgcnVuOiBXb3JrZmxvd1J1bjtcbiAgc3Bhbj86IFNwYW47XG4gIHJlcXVlc3RJZD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTdXNwZW5zaW9uSGFuZGxlclJlc3VsdCB7XG4gIHRpbWVvdXRTZWNvbmRzPzogbnVtYmVyO1xufVxuXG4vKipcbiAqIEhhbmRsZXMgYSB3b3JrZmxvdyBzdXNwZW5zaW9uIGJ5IHByb2Nlc3NpbmcgYWxsIHBlbmRpbmcgb3BlcmF0aW9ucyAoaG9va3MsIHN0ZXBzLCB3YWl0cykuXG4gKiBVc2VzIGFuIGV2ZW50LXNvdXJjZWQgYXJjaGl0ZWN0dXJlIHdoZXJlIGVudGl0aWVzIChzdGVwcywgaG9va3MpIGFyZSBjcmVhdGVkIGF0b21pY2FsbHlcbiAqIHdpdGggdGhlaXIgY29ycmVzcG9uZGluZyBldmVudHMgdmlhIGV2ZW50cy5jcmVhdGUoKS5cbiAqXG4gKiBQcm9jZXNzaW5nIG9yZGVyOlxuICogMS4gSG9va3MgYXJlIHByb2Nlc3NlZCBmaXJzdCB0byBwcmV2ZW50IHJhY2UgY29uZGl0aW9ucyB3aXRoIHdlYmhvb2sgcmVjZWl2ZXJzXG4gKiAyLiBTdGVwcyBhbmQgd2FpdHMgYXJlIHByb2Nlc3NlZCBpbiBwYXJhbGxlbCBhZnRlciBob29rcyBjb21wbGV0ZVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaGFuZGxlU3VzcGVuc2lvbih7XG4gIHN1c3BlbnNpb24sXG4gIHdvcmxkLFxuICBydW4sXG4gIHNwYW4sXG4gIHJlcXVlc3RJZCxcbn06IFN1c3BlbnNpb25IYW5kbGVyUGFyYW1zKTogUHJvbWlzZTxTdXNwZW5zaW9uSGFuZGxlclJlc3VsdD4ge1xuICBjb25zdCBydW5JZCA9IHJ1bi5ydW5JZDtcbiAgY29uc3Qgd29ya2Zsb3dOYW1lID0gcnVuLndvcmtmbG93TmFtZTtcbiAgY29uc3Qgd29ya2Zsb3dTdGFydGVkQXQgPSBydW4uc3RhcnRlZEF0ID8gK3J1bi5zdGFydGVkQXQgOiBEYXRlLm5vdygpO1xuICAvLyBTZXBhcmF0ZSBxdWV1ZSBpdGVtcyBieSB0eXBlXG4gIGNvbnN0IHN0ZXBJdGVtcyA9IHN1c3BlbnNpb24uc3RlcHMuZmlsdGVyKFxuICAgIChpdGVtKTogaXRlbSBpcyBTdGVwSW52b2NhdGlvblF1ZXVlSXRlbSA9PiBpdGVtLnR5cGUgPT09ICdzdGVwJ1xuICApO1xuICBjb25zdCBhbGxIb29rSXRlbXMgPSBzdXNwZW5zaW9uLnN0ZXBzLmZpbHRlcihcbiAgICAoaXRlbSk6IGl0ZW0gaXMgSG9va0ludm9jYXRpb25RdWV1ZUl0ZW0gPT4gaXRlbS50eXBlID09PSAnaG9vaydcbiAgKTtcbiAgY29uc3Qgd2FpdEl0ZW1zID0gc3VzcGVuc2lvbi5zdGVwcy5maWx0ZXIoXG4gICAgKGl0ZW0pOiBpdGVtIGlzIFdhaXRJbnZvY2F0aW9uUXVldWVJdGVtID0+IGl0ZW0udHlwZSA9PT0gJ3dhaXQnXG4gICk7XG5cbiAgLy8gU3BsaXQgaG9va3MgYnkgd2hhdCBhY3Rpb25zIHRoZXkgbmVlZFxuICBjb25zdCBob29rc05lZWRpbmdDcmVhdGlvbiA9IGFsbEhvb2tJdGVtcy5maWx0ZXIoXG4gICAgKGl0ZW0pID0+ICFpdGVtLmhhc0NyZWF0ZWRFdmVudFxuICApO1xuICAvLyBIb29rcyBuZWVkaW5nIGRpc3Bvc2FsOiBhbnkgZGlzcG9zZWQgaG9vayAoaW5jbHVkaW5nIHRob3NlIG5lZWRpbmcgY3JlYXRpb24gZmlyc3QpXG4gIC8vIEhvb2tzIGFyZSBjcmVhdGVkIGJlZm9yZSBkaXNwb3NhbCBpbiB0aGUgcHJvY2Vzc2luZyBvcmRlciBiZWxvd1xuICBjb25zdCBob29rc05lZWRpbmdEaXNwb3NhbCA9IGFsbEhvb2tJdGVtcy5maWx0ZXIoKGl0ZW0pID0+IGl0ZW0uZGlzcG9zZWQpO1xuXG4gIC8vIFJlc29sdmUgZW5jcnlwdGlvbiBrZXkgZm9yIHRoaXMgcnVuXG4gIGNvbnN0IHJhd0tleSA9IGF3YWl0IHdvcmxkLmdldEVuY3J5cHRpb25LZXlGb3JSdW4/LihydW4pO1xuICBjb25zdCBlbmNyeXB0aW9uS2V5ID0gcmF3S2V5ID8gYXdhaXQgaW1wb3J0S2V5KHJhd0tleSkgOiB1bmRlZmluZWQ7XG5cbiAgLy8gQnVpbGQgaG9va19jcmVhdGVkIGV2ZW50cyAoV29ybGQgd2lsbCBhdG9taWNhbGx5IGNyZWF0ZSBob29rIGVudGl0aWVzKVxuICBjb25zdCBob29rRXZlbnRzOiBDcmVhdGVFdmVudFJlcXVlc3RbXSA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgIGhvb2tzTmVlZGluZ0NyZWF0aW9uLm1hcChhc3luYyAocXVldWVJdGVtKSA9PiB7XG4gICAgICBjb25zdCBob29rTWV0YWRhdGE6IFNlcmlhbGl6ZWREYXRhIHwgdW5kZWZpbmVkID1cbiAgICAgICAgdHlwZW9mIHF1ZXVlSXRlbS5tZXRhZGF0YSA9PT0gJ3VuZGVmaW5lZCdcbiAgICAgICAgICA/IHVuZGVmaW5lZFxuICAgICAgICAgIDogKChhd2FpdCBkZWh5ZHJhdGVTdGVwQXJndW1lbnRzKFxuICAgICAgICAgICAgICBxdWV1ZUl0ZW0ubWV0YWRhdGEsXG4gICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICBlbmNyeXB0aW9uS2V5LFxuICAgICAgICAgICAgICBzdXNwZW5zaW9uLmdsb2JhbFRoaXNcbiAgICAgICAgICAgICkpIGFzIFNlcmlhbGl6ZWREYXRhKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGV2ZW50VHlwZTogJ2hvb2tfY3JlYXRlZCcgYXMgY29uc3QsXG4gICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgIHRva2VuOiBxdWV1ZUl0ZW0udG9rZW4sXG4gICAgICAgICAgbWV0YWRhdGE6IGhvb2tNZXRhZGF0YSxcbiAgICAgICAgICBpc1dlYmhvb2s6IHF1ZXVlSXRlbS5pc1dlYmhvb2sgPz8gZmFsc2UsXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH0pXG4gICk7XG5cbiAgLy8gUHJvY2VzcyBob29rcyBmaXJzdCB0byBwcmV2ZW50IHJhY2UgY29uZGl0aW9ucyB3aXRoIHdlYmhvb2sgcmVjZWl2ZXJzXG4gIC8vIEFsbCBob29rIGNyZWF0aW9ucyBydW4gaW4gcGFyYWxsZWxcbiAgLy8gVHJhY2sgYW55IGhvb2sgY29uZmxpY3RzIHRoYXQgb2NjdXIgLSB0aGVzZSB3aWxsIGJlIGhhbmRsZWQgYnkgcmUtZW5xdWV1ZWluZyB0aGUgd29ya2Zsb3dcbiAgbGV0IGhhc0hvb2tDb25mbGljdCA9IGZhbHNlO1xuXG4gIGlmIChob29rRXZlbnRzLmxlbmd0aCA+IDApIHtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIGhvb2tFdmVudHMubWFwKGFzeW5jIChob29rRXZlbnQpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKHJ1bklkLCBob29rRXZlbnQsIHtcbiAgICAgICAgICAgIHJlcXVlc3RJZCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICAvLyBDaGVjayBpZiB0aGUgd29ybGQgcmV0dXJuZWQgYSBob29rX2NvbmZsaWN0IGV2ZW50IGluc3RlYWQgb2YgaG9va19jcmVhdGVkXG4gICAgICAgICAgLy8gVGhlIGhvb2tfY29uZmxpY3QgZXZlbnQgaXMgc3RvcmVkIGluIHRoZSBldmVudCBsb2cgYW5kIHdpbGwgYmUgcmVwbGF5ZWRcbiAgICAgICAgICAvLyBvbiB0aGUgbmV4dCB3b3JrZmxvdyBpbnZvY2F0aW9uLCBjYXVzaW5nIHRoZSBob29rJ3MgcHJvbWlzZSB0byByZWplY3RcbiAgICAgICAgICAvLyBOb3RlOiBob29rIGV2ZW50cyBhbHdheXMgY3JlYXRlIGFuIGV2ZW50IChsZWdhY3kgcnVucyB0aHJvdywgbm90IHJldHVybiB1bmRlZmluZWQpXG4gICAgICAgICAgaWYgKHJlc3VsdC5ldmVudCEuZXZlbnRUeXBlID09PSAnaG9va19jb25mbGljdCcpIHtcbiAgICAgICAgICAgIGhhc0hvb2tDb25mbGljdCA9IHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpIHx8IFJ1bkV4cGlyZWRFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICdXb3JrZmxvdyBydW4gYWxyZWFkeSBjb21wbGV0ZWQsIHNraXBwaW5nIGhvb2snLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIC8vIFByb2Nlc3MgaG9vayBkaXNwb3NhbHMgLSB0aGVzZSByZWxlYXNlIGhvb2sgdG9rZW5zIGZvciByZXVzZSBieSBvdGhlciB3b3JrZmxvd3NcbiAgaWYgKGhvb2tzTmVlZGluZ0Rpc3Bvc2FsLmxlbmd0aCA+IDApIHtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIGhvb2tzTmVlZGluZ0Rpc3Bvc2FsLm1hcChhc3luYyAocXVldWVJdGVtKSA9PiB7XG4gICAgICAgIGNvbnN0IGhvb2tEaXNwb3NlZEV2ZW50OiBDcmVhdGVFdmVudFJlcXVlc3QgPSB7XG4gICAgICAgICAgZXZlbnRUeXBlOiAnaG9va19kaXNwb3NlZCcgYXMgY29uc3QsXG4gICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICB9O1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUocnVuSWQsIGhvb2tEaXNwb3NlZEV2ZW50LCB7IHJlcXVlc3RJZCB9KTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgLy8gSG9vayB3YXMgYWxyZWFkeSBkaXNwb3NlZCBieSBhIGNvbmN1cnJlbnQgaW52b2NhdGlvbiDigJQgc2FmZSB0byBza2lwXG4gICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICdIb29rIGFscmVhZHkgZGlzcG9zZWQsIHNraXBwaW5nIGR1cGxpY2F0ZSBkaXNwb3NhbCcsXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKFJ1bkV4cGlyZWRFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICdXb3JrZmxvdyBydW4gYWxyZWFkeSBjb21wbGV0ZWQsIHNraXBwaW5nIGhvb2sgZGlzcG9zYWwnLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIGlmIChIb29rTm90Rm91bmRFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAvLyBIb29rIG1heSBoYXZlIGFscmVhZHkgYmVlbiBkaXNwb3NlZCBvciBuZXZlciBjcmVhdGVkXG4gICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ0hvb2sgbm90IGZvdW5kIGZvciBkaXNwb3NhbCwgY29udGludWluZycsIHtcbiAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvLyBCdWlsZCBhIG1hcCBvZiBzdGVwSWQgLT4gc3RlcCBldmVudCBmb3Igc3RlcHMgdGhhdCBuZWVkIGNyZWF0aW9uXG4gIGNvbnN0IHN0ZXBzTmVlZGluZ0NyZWF0aW9uID0gbmV3IFNldChcbiAgICBzdGVwSXRlbXNcbiAgICAgIC5maWx0ZXIoKHF1ZXVlSXRlbSkgPT4gIXF1ZXVlSXRlbS5oYXNDcmVhdGVkRXZlbnQpXG4gICAgICAubWFwKChxdWV1ZUl0ZW0pID0+IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKVxuICApO1xuXG4gIC8vIFByb2Nlc3Mgc3RlcHMgYW5kIHdhaXRzIGluIHBhcmFsbGVsXG4gIC8vIEVhY2ggc3RlcDogY3JlYXRlIGV2ZW50IChpZiBuZWVkZWQpIC0+IHF1ZXVlIG1lc3NhZ2VcbiAgLy8gRWFjaCB3YWl0OiBjcmVhdGUgZXZlbnQgKGlmIG5lZWRlZClcbiAgY29uc3Qgb3BzOiBQcm9taXNlPHZvaWQ+W10gPSBbXTtcblxuICAvLyBTdGVwczogY3JlYXRlIGV2ZW50IHRoZW4gcXVldWUgbWVzc2FnZSwgYWxsIGluIHBhcmFsbGVsXG4gIGZvciAoY29uc3QgcXVldWVJdGVtIG9mIHN0ZXBJdGVtcykge1xuICAgIG9wcy5wdXNoKFxuICAgICAgKGFzeW5jICgpID0+IHtcbiAgICAgICAgLy8gQ3JlYXRlIHN0ZXAgZXZlbnQgaWYgbm90IGFscmVhZHkgY3JlYXRlZFxuICAgICAgICBpZiAoc3RlcHNOZWVkaW5nQ3JlYXRpb24uaGFzKHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKSkge1xuICAgICAgICAgIGNvbnN0IGRlaHlkcmF0ZWRJbnB1dCA9IGF3YWl0IGRlaHlkcmF0ZVN0ZXBBcmd1bWVudHMoXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGFyZ3M6IHF1ZXVlSXRlbS5hcmdzLFxuICAgICAgICAgICAgICBjbG9zdXJlVmFyczogcXVldWVJdGVtLmNsb3N1cmVWYXJzLFxuICAgICAgICAgICAgICB0aGlzVmFsOiBxdWV1ZUl0ZW0udGhpc1ZhbCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgIGVuY3J5cHRpb25LZXksXG4gICAgICAgICAgICBzdXNwZW5zaW9uLmdsb2JhbFRoaXNcbiAgICAgICAgICApO1xuICAgICAgICAgIGNvbnN0IHN0ZXBFdmVudDogQ3JlYXRlRXZlbnRSZXF1ZXN0ID0ge1xuICAgICAgICAgICAgZXZlbnRUeXBlOiAnc3RlcF9jcmVhdGVkJyBhcyBjb25zdCxcbiAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgIHN0ZXBOYW1lOiBxdWV1ZUl0ZW0uc3RlcE5hbWUsXG4gICAgICAgICAgICAgIGlucHV0OiBkZWh5ZHJhdGVkSW5wdXQgYXMgU2VyaWFsaXplZERhdGEsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH07XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUocnVuSWQsIHN0ZXBFdmVudCwgeyByZXF1ZXN0SWQgfSk7XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbygnU3RlcCBhbHJlYWR5IGV4aXN0cywgY29udGludWluZycsIHtcbiAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gUXVldWUgc3RlcCBleGVjdXRpb24gbWVzc2FnZVxuICAgICAgICAvLyBTZXJpYWxpemUgdHJhY2UgY29udGV4dCBvbmNlIGFuZCBpbmNsdWRlIGluIGJvdGggcGF5bG9hZCBhbmQgaGVhZGVyc1xuICAgICAgICAvLyBQYXlsb2FkOiBmb3IgbWFudWFsIGNvbnRleHQgcmVzdG9yYXRpb24gaW4gc3RlcCBoYW5kbGVyXG4gICAgICAgIC8vIEhlYWRlcnM6IGZvciBhdXRvbWF0aWMgdHJhY2UgcHJvcGFnYXRpb24gYnkgVmVyY2VsJ3MgaW5mcmFzdHJ1Y3R1cmVcbiAgICAgICAgY29uc3QgdHJhY2VDYXJyaWVyID0gYXdhaXQgc2VyaWFsaXplVHJhY2VDYXJyaWVyKCk7XG4gICAgICAgIGF3YWl0IHF1ZXVlTWVzc2FnZShcbiAgICAgICAgICB3b3JsZCxcbiAgICAgICAgICBgX193a2Zfc3RlcF8ke3F1ZXVlSXRlbS5zdGVwTmFtZX1gLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHdvcmtmbG93TmFtZSxcbiAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgd29ya2Zsb3dTdGFydGVkQXQsXG4gICAgICAgICAgICBzdGVwSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgdHJhY2VDYXJyaWVyLFxuICAgICAgICAgICAgcmVxdWVzdGVkQXQ6IG5ldyBEYXRlKCksXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBpZGVtcG90ZW5jeUtleTogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgICAgIC4uLmV4dHJhY3RUcmFjZUhlYWRlcnModHJhY2VDYXJyaWVyKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgfSkoKVxuICAgICk7XG4gIH1cblxuICAvLyBXYWl0czogY3JlYXRlIGV2ZW50cyBpbiBwYXJhbGxlbCAobm8gcXVldWVpbmcgbmVlZGVkIGZvciB3YWl0cylcbiAgZm9yIChjb25zdCBxdWV1ZUl0ZW0gb2Ygd2FpdEl0ZW1zKSB7XG4gICAgaWYgKCFxdWV1ZUl0ZW0uaGFzQ3JlYXRlZEV2ZW50KSB7XG4gICAgICBvcHMucHVzaChcbiAgICAgICAgKGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCB3YWl0RXZlbnQ6IENyZWF0ZUV2ZW50UmVxdWVzdCA9IHtcbiAgICAgICAgICAgIGV2ZW50VHlwZTogJ3dhaXRfY3JlYXRlZCcgYXMgY29uc3QsXG4gICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICByZXN1bWVBdDogcXVldWVJdGVtLnJlc3VtZUF0LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9O1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKHJ1bklkLCB3YWl0RXZlbnQsIHsgcmVxdWVzdElkIH0pO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ1dhaXQgYWxyZWFkeSBleGlzdHMsIGNvbnRpbnVpbmcnLCB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSkoKVxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvLyBXYWl0IGZvciBhbGwgc3RlcCBhbmQgd2FpdCBvcGVyYXRpb25zIHRvIGNvbXBsZXRlXG4gIHdhaXRVbnRpbChcbiAgICBQcm9taXNlLmFsbChvcHMpLmNhdGNoKChvcEVycikgPT4ge1xuICAgICAgY29uc3QgaXNBYm9ydEVycm9yID1cbiAgICAgICAgb3BFcnI/Lm5hbWUgPT09ICdBYm9ydEVycm9yJyB8fCBvcEVycj8ubmFtZSA9PT0gJ1Jlc3BvbnNlQWJvcnRlZCc7XG4gICAgICBpZiAoIWlzQWJvcnRFcnJvcikgdGhyb3cgb3BFcnI7XG4gICAgfSlcbiAgKTtcbiAgYXdhaXQgUHJvbWlzZS5hbGwob3BzKTtcblxuICAvLyBDYWxjdWxhdGUgbWluaW11bSB0aW1lb3V0IGZyb20gd2FpdHNcbiAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgY29uc3QgbWluVGltZW91dFNlY29uZHMgPSB3YWl0SXRlbXMucmVkdWNlPG51bWJlciB8IG51bGw+KFxuICAgIChtaW4sIHF1ZXVlSXRlbSkgPT4ge1xuICAgICAgY29uc3QgcmVzdW1lQXRNcyA9IHF1ZXVlSXRlbS5yZXN1bWVBdC5nZXRUaW1lKCk7XG4gICAgICBjb25zdCBkZWxheU1zID0gTWF0aC5tYXgoMTAwMCwgcmVzdW1lQXRNcyAtIG5vdyk7XG4gICAgICBjb25zdCB0aW1lb3V0U2Vjb25kcyA9IE1hdGguY2VpbChkZWxheU1zIC8gMTAwMCk7XG4gICAgICBpZiAobWluID09PSBudWxsKSByZXR1cm4gdGltZW91dFNlY29uZHM7XG4gICAgICByZXR1cm4gTWF0aC5taW4obWluLCB0aW1lb3V0U2Vjb25kcyk7XG4gICAgfSxcbiAgICBudWxsXG4gICk7XG5cbiAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgLi4uQXR0cmlidXRlLldvcmtmbG93UnVuU3RhdHVzKCd3b3JrZmxvd19zdXNwZW5kZWQnKSxcbiAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dTdGVwc0NyZWF0ZWQoc3RlcEl0ZW1zLmxlbmd0aCksXG4gICAgLi4uQXR0cmlidXRlLldvcmtmbG93SG9va3NDcmVhdGVkKGhvb2tzTmVlZGluZ0NyZWF0aW9uLmxlbmd0aCksXG4gICAgLi4uQXR0cmlidXRlLldvcmtmbG93V2FpdHNDcmVhdGVkKHdhaXRJdGVtcy5sZW5ndGgpLFxuICB9KTtcblxuICAvLyBJZiBhbnkgaG9vayBjb25mbGljdHMgb2NjdXJyZWQsIHJlLWVucXVldWUgdGhlIHdvcmtmbG93IGltbWVkaWF0ZWx5XG4gIC8vIE9uIHRoZSBuZXh0IGl0ZXJhdGlvbiwgdGhlIGhvb2sgY29uc3VtZXIgd2lsbCBzZWUgdGhlIGhvb2tfY29uZmxpY3QgZXZlbnRcbiAgLy8gYW5kIHJlamVjdCB0aGUgcHJvbWlzZSB3aXRoIGEgV29ya2Zsb3dSdW50aW1lRXJyb3JcbiAgLy8gV2UgZG8gdGhpcyBhZnRlciBwcm9jZXNzaW5nIGFsbCBvdGhlciBvcGVyYXRpb25zIChzdGVwcywgd2FpdHMpIHRvIGVuc3VyZVxuICAvLyB0aGV5IGFyZSByZWNvcmRlZCBpbiB0aGUgZXZlbnQgbG9nIGJlZm9yZSB0aGUgcmUtZXhlY3V0aW9uXG4gIGlmIChoYXNIb29rQ29uZmxpY3QpIHtcbiAgICByZXR1cm4geyB0aW1lb3V0U2Vjb25kczogMCB9O1xuICB9XG5cbiAgaWYgKG1pblRpbWVvdXRTZWNvbmRzICE9PSBudWxsKSB7XG4gICAgcmV0dXJuIHsgdGltZW91dFNlY29uZHM6IG1pblRpbWVvdXRTZWNvbmRzIH07XG4gIH1cblxuICByZXR1cm4ge307XG59XG4iXX0=
484
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3VzcGVuc2lvbi1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bnRpbWUvc3VzcGVuc2lvbi1oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFDTCxtQkFBbUIsRUFDbkIsVUFBVSxFQUNWLGlCQUFpQixFQUNqQixlQUFlLEVBQ2Ysa0JBQWtCLEdBQ25CLE1BQU0sa0JBQWtCLENBQUM7QUFDMUIsT0FBTyxFQUNMLHdCQUF3QixFQUd4QixvQkFBb0IsRUFDcEIsaUNBQWlDLEdBR2xDLE1BQU0saUJBQWlCLENBQUM7QUFDekIsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBUTdDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDN0MsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDN0QsT0FBTyxLQUFLLFNBQVMsTUFBTSxzQ0FBc0MsQ0FBQztBQUNsRSxPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDdkQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFxRm5ELEtBQUssVUFBVSxlQUFlLENBQUMsRUFDN0IsS0FBSyxFQUNMLEtBQUssRUFDTCxTQUFTLEVBQ1QsU0FBUyxFQUNULFNBQVMsR0FPVjtJQUlDLElBQUksQ0FBQztRQUNILE1BQU0sTUFBTSxHQUFHLE1BQU0sS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLFNBQVMsRUFBRTtZQUN6RCxTQUFTO1NBQ1YsQ0FBQyxDQUFDO1FBRUgsNkVBQTZFO1FBQzdFLDBFQUEwRTtRQUMxRSx5RUFBeUU7UUFDekUsSUFBSSxNQUFNLENBQUMsS0FBSyxFQUFFLFNBQVMsS0FBSyxlQUFlLEVBQUUsQ0FBQztZQUNoRCxPQUFPO2dCQUNMLGVBQWUsRUFBRSxJQUFJO2dCQUNyQixzQkFBc0IsRUFBRSxL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LEVBQUUsYUFBYSxDQUFDO1FBQ2xCLEdBQUcsU0FBUyxDQUFDLGlCQUFpQixDQUFDLG9CQUFvQixDQUFDO1FBQ3BELEdBQUcsU0FBUyxDQUFDLG9CQUFvQixDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUM7UUFDbkQsR0FBRyxTQUFTLENBQUMsb0JBQW9CLENBQUMsb0JBQW9CLENBQUMsTUFBTSxDQUFDO1FBQzlELEdBQUcsU0FBUyxDQUFDLG9CQUFvQixDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUM7S0FDcEQsQ0FBQyxDQUFDO0lBRUgsT0FBTztRQUNMLFlBQVksRUFBRSxTQUFTO1FBQ3ZCLHlCQUF5QjtRQUN6QixlQUFlO1FBQ2YscUVBQXFFO1FBQ3JFLHlDQUF5QztRQUN6QyxXQUFXLEVBQUUsZUFBZSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLFdBQVc7UUFDdEQsZUFBZTtRQUNmLHNCQUFzQjtRQUN0QixrQkFBa0IsRUFBRSxjQUFjLENBQUMsTUFBTSxHQUFHLENBQUM7UUFDN0MsYUFBYSxFQUFFLG9CQUFvQixDQUFDLE1BQU0sR0FBRyxDQUFDO1FBQzlDLGNBQWM7S0FDZixDQUFDO0FBQ0osQ0FBQztBQUVEOzs7Ozs7OztHQVFHO0FBQ0gsU0FBUyw0QkFBNEIsQ0FBQyxHQUFZO0lBQ2hELElBQUksR0FBRyxZQUFZLHdCQUF3QjtRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQ3pELElBQUksR0FBRyxZQUFZLEtBQUssSUFBSSxHQUFHLENBQUMsSUFBSSxLQUFLLDBCQUEwQixFQUFFLENBQUM7UUFDcEUsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBQ0QsT0FBTyxrQkFBa0IsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksR0FBRyxDQUFDLE1BQU0sS0FBSyxHQUFHLENBQUM7QUFDMUQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgU3BhbiB9IGZyb20gJ0BvcGVudGVsZW1ldHJ5L2FwaSc7XG5pbXBvcnQge1xuICBFbnRpdHlDb25mbGljdEVycm9yLFxuICBGYXRhbEVycm9yLFxuICBIb29rTm90Rm91bmRFcnJvcixcbiAgUnVuRXhwaXJlZEVycm9yLFxuICBXb3JrZmxvd1dvcmxkRXJyb3IsXG59IGZyb20gJ0B3b3JrZmxvdy9lcnJvcnMnO1xuaW1wb3J0IHtcbiAgQXR0cmlidXRlVmFsaWRhdGlvbkVycm9yLFxuICB0eXBlIENyZWF0ZUV2ZW50UmVxdWVzdCxcbiAgdHlwZSBTZXJpYWxpemVkRGF0YSxcbiAgU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gIFNQRUNfVkVSU0lPTl9TVVBQT1JUU19DT01QUkVTU0lPTixcbiAgdHlwZSBXb3JrZmxvd1J1bixcbiAgdHlwZSBXb3JsZCxcbn0gZnJvbSAnQHdvcmtmbG93L3dvcmxkJztcbmltcG9ydCB7IGltcG9ydEtleSB9IGZyb20gJy4uL2VuY3J5cHRpb24uanMnO1xuaW1wb3J0IHR5cGUge1xuICBBdHRyaWJ1dGVJbnZvY2F0aW9uUXVldWVJdGVtLFxuICBIb29rSW52b2NhdGlvblF1ZXVlSXRlbSxcbiAgU3RlcEludm9jYXRpb25RdWV1ZUl0ZW0sXG4gIFdhaXRJbnZvY2F0aW9uUXVldWVJdGVtLFxuICBXb3JrZmxvd1N1c3BlbnNpb24sXG59IGZyb20gJy4uL2dsb2JhbC5qcyc7XG5pbXBvcnQgeyBydW50aW1lTG9nZ2VyIH0gZnJvbSAnLi4vbG9nZ2VyLmpzJztcbmltcG9ydCB7IGRlaHlkcmF0ZVN0ZXBBcmd1bWVudHMgfSBmcm9tICcuLi9zZXJpYWxpemF0aW9uLmpzJztcbmltcG9ydCAqIGFzIEF0dHJpYnV0ZSBmcm9tICcuLi90ZWxlbWV0cnkvc2VtYW50aWMtY29udmVudGlvbnMuanMnO1xuaW1wb3J0IHsgZ2V0QWJvcnRTdHJlYW1JZEZyb21Ub2tlbiB9IGZyb20gJy4uL3V0aWwuanMnO1xuaW1wb3J0IHsgZ2V0TWF4SW5saW5lU3RlcHMgfSBmcm9tICcuL2NvbnN0YW50cy5qcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3VzcGVuc2lvbkhhbmRsZXJQYXJhbXMge1xuICBzdXNwZW5zaW9uOiBXb3JrZmxvd1N1c3BlbnNpb247XG4gIHdvcmxkOiBXb3JsZDtcbiAgcnVuOiBXb3JrZmxvd1J1bjtcbiAgc3Bhbj86IFNwYW47XG4gIHJlcXVlc3RJZD86IHN0cmluZztcbiAgLyoqXG4gICAqIFR1cmJvIG1vZGUgb25seTogYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgb25jZSB0aGUgYmFja2dyb3VuZGVkXG4gICAqIGBydW5fc3RhcnRlZGAgaGFzIGxhbmRlZCAodGhlIHJ1biBleGlzdHMpLiBXaGVuIHByZXNlbnQsIGV2ZXJ5IHdvcmxkIHdyaXRlXG4gICAqIHRoaXMgc3VzcGVuc2lvbiBwZXJmb3JtcyAoYGhvb2tfY3JlYXRlZGAsIGB3YWl0X2NyZWF0ZWRgLCBlYWdlciBvdmVyZmxvd1xuICAgKiBgc3RlcF9jcmVhdGVkYCwg4oCmKSBpcyBnYXRlZCBvbiBpdCBzbyB0aGUgd3JpdGUgbmV2ZXIgcmFjZXMgYWhlYWQgb2YgdGhlXG4gICAqIHJ1bidzIGNyZWF0aW9uLiBUaGUgcHVyZSBpbmxpbmUgaG90IHBhdGggZGVmZXJzIGFsbCBvZiBpdHMgc3RlcHMgYW5kIHdyaXRlc1xuICAgKiBub3RoaW5nIGhlcmUsIHNvIGl0IG5ldmVyIGF3YWl0cyB0aGlzIGJhcnJpZXIuIGB1bmRlZmluZWRgIG91dHNpZGUgdHVyYm8sXG4gICAqIHdoZXJlIGBydW5fc3RhcnRlZGAgd2FzIGFscmVhZHkgYXdhaXRlZCB1cCBmcm9udC5cbiAgICovXG4gIHJ1blJlYWR5QmFycmllcj86IFByb21pc2U8dW5rbm93bj47XG59XG5cbi8qKlxuICogUmVzdWx0IG9mIGhhbmRsaW5nIGEgc3VzcGVuc2lvbi4gUmV0dXJucyBwZW5kaW5nIHN0ZXAgaXRlbXMgc28gdGhlIGNhbGxlclxuICogY2FuIGRlY2lkZSB3aGljaCB0byBleGVjdXRlIGlubGluZSB2cyBxdWV1ZSB0byBiYWNrZ3JvdW5kLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFN1c3BlbnNpb25IYW5kbGVyUmVzdWx0IHtcbiAgLyoqIFBlbmRpbmcgc3RlcCBpdGVtcyB3aXRoIGV2ZW50cyBjcmVhdGVkIGJ1dCBOT1QgcXVldWVkICovXG4gIHBlbmRpbmdTdGVwczogU3RlcEludm9jYXRpb25RdWV1ZUl0ZW1bXTtcbiAgLyoqXG4gICAqIENvcnJlbGF0aW9uIElEcyBmb3Igd2hpY2ggdGhpcyBzdXNwZW5zaW9uIGNhbGwgYWN0dWFsbHkgd3JvdGUgdGhlXG4gICAqIHN0ZXBfY3JlYXRlZCBldmVudCAoYXMgb3Bwb3NlZCB0byBjYXRjaGluZyBFbnRpdHlDb25mbGljdEVycm9yIGJlY2F1c2VcbiAgICogYSBjb25jdXJyZW50IGhhbmRsZXIgd3JvdGUgaXQgZmlyc3QpLiBPbmx5IHRoZSBoYW5kbGVyIHRoYXQgd3JvdGUgdGhlXG4gICAqIHN0ZXBfY3JlYXRlZCBldmVudCBzaG91bGQgcXVldWUgLyBpbmxpbmUtZXhlY3V0ZSB0aGUgc3RlcCDigJQgdGhpc1xuICAgKiBndWFyYW50ZWVzIGEgc2luZ2xlIG93bmVyIHBlciBzdGVwLCBldmVuIHdoZW4gbXVsdGlwbGUgaGFuZGxlcnMgcmFjZVxuICAgKiBpbnRvIHRoZSBzYW1lIGJhdGNoIGJvdW5kYXJ5LlxuICAgKi9cbiAgY3JlYXRlZFN0ZXBDb3JyZWxhdGlvbklkczogU2V0PHN0cmluZz47XG4gIC8qKlxuICAgKiBUaGUgc3RlcHMgd2hvc2UgYHN0ZXBfY3JlYXRlZGAgd3JpdGVzIHdlcmUgaW50ZW50aW9uYWxseSBkZWZlcnJlZCBzbyB0aGVcbiAgICogY2FsbGVyIGNhbiBydW4gdGhlbSBpbmxpbmUgdmlhIGxhenkgYHN0ZXBfc3RhcnRlZGAgZXZlbnRzICh3aGljaCBjcmVhdGVcbiAgICogdGhlIHN0ZXAgb24gdGhlIGZseSksIHNhdmluZyBvbmUgd29ybGQgcm91bmQtdHJpcCBwZXIgaW5saW5lIHN0ZXAuIFVwIHRvXG4gICAqIGBnZXRNYXhJbmxpbmVTdGVwcygpYCBzdGVwcyBhcmUgZGVmZXJyZWQ7IHRoZSBjYWxsZXIgcnVucyB0aGVtIGlubGluZSBpblxuICAgKiBwYXJhbGxlbCBhbmQgcXVldWVzIHRoZSByZXN0LiBFbXB0eSB3aGVuIG5vIHN0ZXAgd2FzIGRlZmVycmVkIChub3RoaW5nXG4gICAqIHBlbmRpbmcsIG9yIGEgYGhvb2suZ2V0Q29uZmxpY3QoKWAgYXdhaXRlciBpcyBwcmVzZW50IHNvIG5vdGhpbmcgaXNcbiAgICogZXhlY3V0ZWQgaW5saW5lKS4gVGhlIGNhbGxlciBwYXNzZXMgZWFjaCBgZGVoeWRyYXRlZElucHV0YCBzdHJhaWdodCB0b1xuICAgKiBgZXhlY3V0ZVN0ZXBgLCB3aGljaCBzZW5kcyBpdCBhcyB0aGUgYHN0ZXBfc3RhcnRlZGAgcGF5bG9hZC4gVGhlIGF0b21pY1xuICAgKiBjcmVhdGUtY2xhaW0gaW5zaWRlIGVhY2ggYHN0ZXBfc3RhcnRlZGAgaXMgdGhlIGV4YWN0bHktb25lLW93bmVyIGdhdGUgdGhhdFxuICAgKiB0aGUgc3RhbmRhbG9uZSBgc3RlcF9jcmVhdGVkYCBwcm92aWRlZCBiZWZvcmU6IHRoZSBsb3NlciBvZiB0aGUgcmFjZSBnZXRzXG4gICAqIGBFbnRpdHlDb25mbGljdEVycm9yYCDihpIgYHNraXBwZWRgIGFuZCBkb2VzIG5vdCBydW4gdGhlIGJvZHkuXG4gICAqL1xuICBsYXp5SW5saW5lU3RlcHM6IEFycmF5PHtcbiAgICBjb3JyZWxhdGlvbklkOiBzdHJpbmc7XG4gICAgc3RlcE5hbWU6IHN0cmluZztcbiAgICBkZWh5ZHJhdGVkSW5wdXQ6IFNlcmlhbGl6ZWREYXRhO1xuICB9PjtcbiAgLyoqXG4gICAqIFRoZSBzb29uZXN0IHBlbmRpbmcgd2FpdCwgaWYgYW55OiBzZWNvbmRzIHVudGlsIGl0IGVsYXBzZXMgYW5kIHRoZVxuICAgKiBjb3JyZWxhdGlvbklkIG9mIHRoZSB3YWl0IHRoYXQgcHJvZHVjZWQgdGhhdCB0aW1lb3V0LiBUaGVcbiAgICogY29ycmVsYXRpb25JZCBzZWVkcyB0aGUgaWRlbXBvdGVuY3kga2V5IGZvciB0aGUgd2FpdC1jb250aW51YXRpb25cbiAgICogcXVldWUgbWVzc2FnZSBzbyB0aGF0IHJlcGVhdGVkIHN1c3BlbnNpb24gcGFzc2VzIG92ZXIgdGhlIHNhbWVcbiAgICogcGVuZGluZyB3YWl0IGNvbGxhcHNlIGludG8gYSBzaW5nbGUgZGVsYXllZCBjb250aW51YXRpb24uXG4gICAqL1xuICB3YWl0VGltZW91dD86IHsgc2Vjb25kczogbnVtYmVyOyBjb3JyZWxhdGlvbklkOiBzdHJpbmcgfTtcbiAgLyoqIFdoZXRoZXIgYSBob29rIGNvbmZsaWN0IHdhcyBkZXRlY3RlZCAoc2hvdWxkIHJlLWludm9rZSBpbW1lZGlhdGVseSkgKi9cbiAgaGFzSG9va0NvbmZsaWN0OiBib29sZWFuO1xuICAvKiogV2hldGhlciBhIGBob29rLmdldENvbmZsaWN0KClgIGF3YWl0ZXIgbmVlZHMgdGhlIHdvcmtmbG93IHRvIGNvbnRpbnVlIGltbWVkaWF0ZWx5ICovXG4gIGhhc0F3YWl0ZWRIb29rQ3JlYXRpb246IGJvb2xlYW47XG4gIC8qKiBXaGV0aGVyIG5hdGl2ZSB3b3JrZmxvdyBhdHRyaWJ1dGUgZXZlbnRzIHdlcmUgd3JpdHRlbiBmb3IgcmVwbGF5LiAqL1xuICBoYXNBdHRyaWJ1dGVFdmVudHM6IGJvb2xlYW47XG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoaXMgc3VzcGVuc2lvbiBjcmVhdGVkIGFueSBob29rIChgaG9va19jcmVhdGVkYCkgZXZlbnRzLiBVbmxpa2VcbiAgICogYGhhc0hvb2tDb25mbGljdGAgLyBgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbmAsIHRoaXMgaXMgdHJ1ZSBldmVuIGZvciBhIHBsYWluXG4gICAqIGZpcmUtYW5kLWZvcmdldCBob29rIHdpdGggbm8gY29uZmxpY3QgYW5kIG5vIGF3YWl0ZXIuIFR1cmJvIG1vZGUgdXNlcyBpdCB0b1xuICAgKiBkZXRlY3QgXCJhIGhvb2sgd2FzIGNyZWF0ZWQgdGhpcyBzdXNwZW5zaW9uXCIgYW5kIHN0b3AgZm9yY2luZyBvcHRpbWlzdGljXG4gICAqIGlubGluZSBzdGFydCAoYSBob29rIGludHJvZHVjZXMgbGF0ZXIgcmVzdW1lIGludm9jYXRpb25zIHRoYXQgY291bGQgcmFjZSkuXG4gICAqL1xuICBoYXNIb29rRXZlbnRzOiBib29sZWFuO1xuICAvKipcbiAgICogV2FsbC1jbG9jayBtcyBzcGVudCBjb21taXR0aW5nIHRoaXMgc3VzcGVuc2lvbidzIGBob29rX2NyZWF0ZWRgIGV2ZW50c1xuICAgKiAoMCB3aGVuIGl0IGNyZWF0ZWQgbm9uZSkuIFRoZSBjYWxsZXIgYWNjdW11bGF0ZXMgdGhpcyBhY3Jvc3MgaXRlcmF0aW9uc1xuICAgKiBhbmQgc3VidHJhY3RzIGl0IGZyb20gdGhlIFRURlMgbGF0ZW5jeSBtZWFzdXJlbWVudCwgc28gdGltZSBzcGVudFxuICAgKiBkdXJhYmx5IGNyZWF0aW5nIHRoZSB1c2VyJ3MgaG9va3MgZG9lc24ndCBjb3VudCBhcyBydW50aW1lIG92ZXJoZWFkLlxuICAgKi9cbiAgaG9va0NyZWF0aW9uTXM6IG51bWJlcjtcbn1cblxuYXN5bmMgZnVuY3Rpb24gY3JlYXRlSG9va0V2ZW50KHtcbiAgd29ybGQsXG4gIHJ1bklkLFxuICBob29rRXZlbnQsXG4gIHF1ZXVlSXRlbSxcbiAgcmVxdWVzdElkLFxufToge1xuICB3b3JsZDogV29ybGQ7XG4gIHJ1bklkOiBzdHJpbmc7XG4gIGhvb2tFdmVudDogQ3JlYXRlRXZlbnRSZXF1ZXN0O1xuICBxdWV1ZUl0ZW06IEhvb2tJbnZvY2F0aW9uUXVldWVJdGVtO1xuICByZXF1ZXN0SWQ/OiBzdHJpbmc7XG59KTogUHJvbWlzZTx7XG4gIGhhc0hvb2tDb25mbGljdDogYm9vbGVhbjtcbiAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbjogYm9vbGVhbjtcbn0+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKHJ1bklkLCBob29rRXZlbnQsIHtcbiAgICAgIHJlcXVlc3RJZCxcbiAgICB9KTtcblxuICAgIC8vIENoZWNrIGlmIHRoZSB3b3JsZCByZXR1cm5lZCBhIGhvb2tfY29uZmxpY3QgZXZlbnQgaW5zdGVhZCBvZiBob29rX2NyZWF0ZWQuXG4gICAgLy8gVGhlIGhvb2tfY29uZmxpY3QgZXZlbnQgaXMgc3RvcmVkIGluIHRoZSBldmVudCBsb2cgYW5kIHdpbGwgYmUgcmVwbGF5ZWRcbiAgICAvLyBvbiB0aGUgbmV4dCB3b3JrZmxvdyBpbnZvY2F0aW9uLCBjYXVzaW5nIHRoZSBob29rJ3MgcHJvbWlzZSB0byByZWplY3QuXG4gICAgaWYgKHJlc3VsdC5ldmVudD8uZXZlbnRUeXBlID09PSAnaG9va19jb25mbGljdCcpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGhhc0hvb2tDb25mbGljdDogdHJ1ZSxcbiAgICAgICAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbjogZmFsc2UsXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBoYXNIb29rQ29uZmxpY3Q6IGZhbHNlLFxuICAgICAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbjogcXVldWVJdGVtLmhhc0NvbmZsaWN0QXdhaXRlciA9PT0gdHJ1ZSxcbiAgICB9O1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ0hvb2sgYWxyZWFkeSBleGlzdHMsIGNvbnRpbnVpbmcnLCB7XG4gICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaGFzSG9va0NvbmZsaWN0OiBmYWxzZSxcbiAgICAgICAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbjogcXVldWVJdGVtLmhhc0NvbmZsaWN0QXdhaXRlciA9PT0gdHJ1ZSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKFJ1bkV4cGlyZWRFcnJvci5pcyhlcnIpKSB7XG4gICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ1dvcmtmbG93IHJ1biBhbHJlYWR5IGNvbXBsZXRlZCwgc2tpcHBpbmcgaG9vaycsIHtcbiAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgfSk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBoYXNIb29rQ29uZmxpY3Q6IGZhbHNlLFxuICAgICAgICBoYXNBd2FpdGVkSG9va0NyZWF0aW9uOiBmYWxzZSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgdGhyb3cgZXJyO1xuICB9XG59XG5cbi8qKlxuICogSGFuZGxlcyBhIHdvcmtmbG93IHN1c3BlbnNpb24gYnkgcHJvY2Vzc2luZyBhbGwgcGVuZGluZyBvcGVyYXRpb25zIChob29rcywgc3RlcHMsIHdhaXRzKS5cbiAqIENyZWF0ZXMgZXZlbnRzIGZvciBhbGwgb3BlcmF0aW9ucyBidXQgZG9lcyBOT1QgcXVldWUgc3RlcCBtZXNzYWdlcyDigJQgcmV0dXJucyB0aGUgcGVuZGluZ1xuICogc3RlcHMgc28gdGhlIGNhbGxlciBjYW4gZGVjaWRlIHdoaWNoIHRvIGV4ZWN1dGUgaW5saW5lIHZzIHF1ZXVlIHRvIGJhY2tncm91bmQuXG4gKlxuICogUHJvY2Vzc2luZyBvcmRlcjpcbiAqIDEuIEhvb2tzIGFyZSBwcm9jZXNzZWQgZmlyc3QgdG8gcHJldmVudCByYWNlIGNvbmRpdGlvbnMgd2l0aCB3ZWJob29rIHJlY2VpdmVyc1xuICogMi4gU3RlcCBldmVudHMgYW5kIHdhaXQgZXZlbnRzIGFyZSBjcmVhdGVkIGluIHBhcmFsbGVsXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYW5kbGVTdXNwZW5zaW9uKHtcbiAgc3VzcGVuc2lvbixcbiAgd29ybGQsXG4gIHJ1bixcbiAgc3BhbixcbiAgcmVxdWVzdElkLFxuICBydW5SZWFkeUJhcnJpZXIsXG59OiBTdXNwZW5zaW9uSGFuZGxlclBhcmFtcyk6IFByb21pc2U8U3VzcGVuc2lvbkhhbmRsZXJSZXN1bHQ+IHtcbiAgY29uc3QgcnVuSWQgPSBydW4ucnVuSWQ7XG4gIC8vIFR1cmJvIG1vZGU6IGhvbGQgZXZlcnkgd29ybGQgd3JpdGUgYmVsb3cgdW50aWwgdGhlIGJhY2tncm91bmRlZFxuICAvLyBgcnVuX3N0YXJ0ZWRgIGhhcyAqc2V0dGxlZCosIHNvIHdlIG5ldmVyIHdyaXRlIGEgc3RlcC9ob29rL3dhaXQgZXZlbnQgZm9yIGFcbiAgLy8gcnVuIHRoYXQgZG9lcyBub3QgZXhpc3QgeWV0LiBBIG5vLW9wIG91dHNpZGUgdHVyYm8gKGJhcnJpZXIgdW5kZWZpbmVkKSBhbmRcbiAgLy8gb24gdGhlIHB1cmUgaW5saW5lIGhvdCBwYXRoLCB3aGljaCBkZWZlcnMgYWxsIHN0ZXBzIGFuZCB3cml0ZXMgbm90aGluZy5cbiAgLy8gQXdhaXRpbmcgdGhlIHNhbWUgKHVzdWFsbHkgYWxyZWFkeS1zZXR0bGVkKSBwcm9taXNlIG1vcmUgdGhhbiBvbmNlIGlzIGNoZWFwLlxuICAvLyBBIGJhcnJpZXIgcmVqZWN0aW9uIGlzIHN3YWxsb3dlZCBmb3Igb3JkZXJpbmcgb25seTogaWYgYHJ1bl9zdGFydGVkYCB0cnVseVxuICAvLyBmYWlsZWQgdGhlIHJ1biBkb2VzIG5vdCBleGlzdCwgc28gdGhlIHN1YnNlcXVlbnQgd3JpdGUgc3VyZmFjZXMgdGhlIHJlYWxcbiAgLy8gZXJyb3IgKHJ1biBub3QgZm91bmQgLyBnb25lKSBhbmQgdGhlIG1lc3NhZ2UgcmVkZWxpdmVycy5cbiAgY29uc3QgZW5zdXJlUnVuUmVhZHkgPSBhc3luYyAoKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgaWYgKHJ1blJlYWR5QmFycmllcikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgcnVuUmVhZHlCYXJyaWVyO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIGludGVudGlvbmFsOiBvcmRlcmluZyBiYXJyaWVyIG9ubHkg4oCUIHNlZSBhYm92ZS5cbiAgICAgIH1cbiAgICB9XG4gIH07XG4gIC8vIFNlcGFyYXRlIHF1ZXVlIGl0ZW1zIGJ5IHR5cGVcbiAgY29uc3Qgc3RlcEl0ZW1zID0gc3VzcGVuc2lvbi5zdGVwcy5maWx0ZXIoXG4gICAgKGl0ZW0pOiBpdGVtIGlzIFN0ZXBJbnZvY2F0aW9uUXVldWVJdGVtID0+IGl0ZW0udHlwZSA9PT0gJ3N0ZXAnXG4gICk7XG4gIGNvbnN0IGFsbEhvb2tJdGVtcyA9IHN1c3BlbnNpb24uc3RlcHMuZmlsdGVyKFxuICAgIChpdGVtKTogaXRlbSBpcyBIb29rSW52b2NhdGlvblF1ZXVlSXRlbSA9PiBpdGVtLnR5cGUgPT09ICdob29rJ1xuICApO1xuICBjb25zdCB3YWl0SXRlbXMgPSBzdXNwZW5zaW9uLnN0ZXBzLmZpbHRlcihcbiAgICAoaXRlbSk6IGl0ZW0gaXMgV2FpdEludm9jYXRpb25RdWV1ZUl0ZW0gPT4gaXRlbS50eXBlID09PSAnd2FpdCdcbiAgKTtcbiAgY29uc3QgYXR0cmlidXRlSXRlbXMgPSBzdXNwZW5zaW9uLnN0ZXBzLmZpbHRlcihcbiAgICAoaXRlbSk6IGl0ZW0gaXMgQXR0cmlidXRlSW52b2NhdGlvblF1ZXVlSXRlbSA9PiBpdGVtLnR5cGUgPT09ICdhdHRyaWJ1dGUnXG4gICk7XG5cbiAgY29uc3QgaG9va3NOZWVkaW5nQ3JlYXRpb24gPSBhbGxIb29rSXRlbXMuZmlsdGVyKFxuICAgIChpdGVtKSA9PiAhaXRlbS5oYXNDcmVhdGVkRXZlbnRcbiAgKTtcblxuICAvLyBHcm91cCBob29rIGl0ZW1zIHRoYXQgbmVlZCB3b3JrIGJ5IHRva2VuLCBwcmVzZXJ2aW5nIHF1ZXVlLWluc2VydGlvblxuICAvLyAod29ya2Zsb3cgY29kZSkgb3JkZXIgd2l0aGluIGVhY2ggdG9rZW4uIE9wZXJhdGlvbnMgb24gb25lIHRva2VuIG11c3RcbiAgLy8gYXBwbHkgaW4gY29kZSBvcmRlcjogYSBkaXNwb3NlKCkgb2YgYW4gZWFybGllciBob29rIHJlbGVhc2VzIHRoZSB0b2tlblxuICAvLyBiZWZvcmUgYSBsYXRlciBzYW1lLXRva2VuIGhvb2sncyBjcmVhdGlvbiBpcyB2YWxpZGF0ZWQg4oCUIG90aGVyd2lzZSB0aGVcbiAgLy8gbmV3IGhvb2sgcmVjb3JkcyBhIHNwdXJpb3VzIGhvb2tfY29uZmxpY3QgYWdhaW5zdCB0aGUgcnVuJ3Mgb3duXG4gIC8vIGRpc3Bvc2VkIGhvb2sg4oCUIHdoaWxlIGEgaG9vayBjcmVhdGVkIGFuZCBkaXNwb3NlZCB3aXRoaW4gdGhlIHNhbWVcbiAgLy8gc3VzcGVuc2lvbiBpcyBzdGlsbCBjcmVhdGVkIGJlZm9yZSBpdCBpcyBkaXNwb3NlZC4gRGlmZmVyZW50IHRva2Vuc1xuICAvLyBoYXZlIG5vIGNsYWltIGludGVyYWN0aW9uLCBzbyB0b2tlbiBncm91cHMgYXJlIHByb2Nlc3NlZCBpbiBwYXJhbGxlbC5cbiAgY29uc3QgaG9va0l0ZW1zQnlUb2tlbiA9IG5ldyBNYXA8c3RyaW5nLCBIb29rSW52b2NhdGlvblF1ZXVlSXRlbVtdPigpO1xuICBmb3IgKGNvbnN0IGl0ZW0gb2YgYWxsSG9va0l0ZW1zKSB7XG4gICAgaWYgKGl0ZW0uaGFzQ3JlYXRlZEV2ZW50ICYmICFpdGVtLmRpc3Bvc2VkKSB7XG4gICAgICBjb250aW51ZTsgLy8gYWxyZWFkeSBjb21taXR0ZWQgYW5kIHN0aWxsIGxpdmUg4oCUIG5vdGhpbmcgdG8gZG9cbiAgICB9XG4gICAgY29uc3QgZ3JvdXAgPSBob29rSXRlbXNCeVRva2VuLmdldChpdGVtLnRva2VuKTtcbiAgICBpZiAoZ3JvdXApIHtcbiAgICAgIGdyb3VwLnB1c2goaXRlbSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGhvb2tJdGVtc0J5VG9rZW4uc2V0KGl0ZW0udG9rZW4sIFtpdGVtXSk7XG4gICAgfVxuICB9XG5cbiAgLy8gUmVzb2x2ZSBlbmNyeXB0aW9uIGtleSBmb3IgdGhpcyBydW5cbiAgY29uc3QgcmF3S2V5ID0gYXdhaXQgd29ybGQuZ2V0RW5jcnlwdGlvbktleUZvclJ1bj8uKHJ1bik7XG4gIGNvbnN0IGVuY3J5cHRpb25LZXkgPSByYXdLZXkgPyBhd2FpdCBpbXBvcnRLZXkocmF3S2V5KSA6IHVuZGVmaW5lZDtcblxuICAvLyBHYXRlIHBheWxvYWQgY29tcHJlc3Npb24gb24gdGhlIHJ1bidzIHNwZWNWZXJzaW9uOiBvbmx5IHJ1bnMgbWFya2VkXG4gIC8vIGFzIHBvc3NpYmx5IGNvbnRhaW5pbmcgY29tcHJlc3NlZCBwYXlsb2FkcyAoc3BlYyA+PSA1KSBnZXQgZ3ppcCBkYXRhLlxuICBjb25zdCBjb21wcmVzc2lvbiA9XG4gICAgKHJ1bi5zcGVjVmVyc2lvbiA/PyAwKSA+PSBTUEVDX1ZFUlNJT05fU1VQUE9SVFNfQ09NUFJFU1NJT047XG5cbiAgYXN5bmMgZnVuY3Rpb24gZGlzcG9zZUhvb2soXG4gICAgcXVldWVJdGVtOiBIb29rSW52b2NhdGlvblF1ZXVlSXRlbVxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBob29rRGlzcG9zZWRFdmVudDogQ3JlYXRlRXZlbnRSZXF1ZXN0ID0ge1xuICAgICAgZXZlbnRUeXBlOiAnaG9va19kaXNwb3NlZCcgYXMgY29uc3QsXG4gICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICB0b2tlbjogcXVldWVJdGVtLnRva2VuLFxuICAgICAgfSxcbiAgICB9O1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKHJ1bklkLCBob29rRGlzcG9zZWRFdmVudCwgeyByZXF1ZXN0SWQgfSk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgIC8vIEhvb2sgd2FzIGFscmVhZHkgZGlzcG9zZWQgYnkgYSBjb25jdXJyZW50IGludm9jYXRpb24g4oCUIHNhZmUgdG8gc2tpcFxuICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgJ0hvb2sgYWxyZWFkeSBkaXNwb3NlZCwgc2tpcHBpbmcgZHVwbGljYXRlIGRpc3Bvc2FsJyxcbiAgICAgICAgICB7XG4gICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgfSBlbHNlIGlmIChSdW5FeHBpcmVkRXJyb3IuaXMoZXJyKSkge1xuICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgJ1dvcmtmbG93IHJ1biBhbHJlYWR5IGNvbXBsZXRlZCwgc2tpcHBpbmcgaG9vayBkaXNwb3NhbCcsXG4gICAgICAgICAge1xuICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSBpZiAoSG9va05vdEZvdW5kRXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAvLyBIb29rIG1heSBoYXZlIGFscmVhZHkgYmVlbiBkaXNwb3NlZCBvciBuZXZlciBjcmVhdGVkXG4gICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbygnSG9vayBub3QgZm91bmQgZm9yIGRpc3Bvc2FsLCBjb250aW51aW5nJywge1xuICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBQcm9jZXNzIGhvb2tzIGZpcnN0IHRvIHByZXZlbnQgcmFjZSBjb25kaXRpb25zIHdpdGggd2ViaG9vayByZWNlaXZlcnMuXG4gIC8vIFRyYWNrIGFueSBob29rIGNvbmZsaWN0cyB0aGF0IG9jY3VyIOKAlCB0aGVzZSBhcmUgcmV0dXJuZWQgdG8gdGhlIGNhbGxlclxuICAvLyBzbyB0aGUgVjIgaGFuZGxlciBjYW4gcmUtaW52b2tlIGltbWVkaWF0ZWx5LlxuICBsZXQgaGFzSG9va0NvbmZsaWN0ID0gZmFsc2U7XG4gIGxldCBoYXNBd2FpdGVkSG9va0NyZWF0aW9uID0gZmFsc2U7XG4gIGxldCBob29rQ3JlYXRpb25NcyA9IDA7XG5cbiAgaWYgKGhvb2tJdGVtc0J5VG9rZW4uc2l6ZSA+IDApIHtcbiAgICBjb25zdCBob29rUGhhc2VTdGFydCA9IERhdGUubm93KCk7XG4gICAgYXdhaXQgZW5zdXJlUnVuUmVhZHkoKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIFsuLi5ob29rSXRlbXNCeVRva2VuLnZhbHVlcygpXS5tYXAoYXN5bmMgKGl0ZW1zKSA9PiB7XG4gICAgICAgIGZvciAoY29uc3QgcXVldWVJdGVtIG9mIGl0ZW1zKSB7XG4gICAgICAgICAgbGV0IGNyZWF0aW9uQ29uZmxpY3RlZCA9IGZhbHNlO1xuXG4gICAgICAgICAgaWYgKCFxdWV1ZUl0ZW0uaGFzQ3JlYXRlZEV2ZW50KSB7XG4gICAgICAgICAgICBjb25zdCBob29rTWV0YWRhdGE6IFNlcmlhbGl6ZWREYXRhIHwgdW5kZWZpbmVkID1cbiAgICAgICAgICAgICAgdHlwZW9mIHF1ZXVlSXRlbS5tZXRhZGF0YSA9PT0gJ3VuZGVmaW5lZCdcbiAgICAgICAgICAgICAgICA/IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgIDogKChhd2FpdCBkZWh5ZHJhdGVTdGVwQXJndW1lbnRzKFxuICAgICAgICAgICAgICAgICAgICBxdWV1ZUl0ZW0ubWV0YWRhdGEsXG4gICAgICAgICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICBlbmNyeXB0aW9uS2V5LFxuICAgICAgICAgICAgICAgICAgICBzdXNwZW5zaW9uLmdsb2JhbFRoaXMsXG4gICAgICAgICAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBjb21wcmVzc2lvblxuICAgICAgICAgICAgICAgICAgKSkgYXMgU2VyaWFsaXplZERhdGEpO1xuICAgICAgICAgICAgY29uc3QgaG9va0V2ZW50OiBDcmVhdGVFdmVudFJlcXVlc3QgPSB7XG4gICAgICAgICAgICAgIGV2ZW50VHlwZTogJ2hvb2tfY3JlYXRlZCcgYXMgY29uc3QsXG4gICAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgIHRva2VuOiBxdWV1ZUl0ZW0udG9rZW4sXG4gICAgICAgICAgICAgICAgbWV0YWRhdGE6IGhvb2tNZXRhZGF0YSxcbiAgICAgICAgICAgICAgICBpc1dlYmhvb2s6IHF1ZXVlSXRlbS5pc1dlYmhvb2sgPz8gZmFsc2UsXG4gICAgICAgICAgICAgICAgLi4uKHF1ZXVlSXRlbS5pc1N5c3RlbSAmJiB7IGlzU3lzdGVtOiB0cnVlIH0pLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNyZWF0ZUhvb2tFdmVudCh7XG4gICAgICAgICAgICAgIHdvcmxkLFxuICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgaG9va0V2ZW50LFxuICAgICAgICAgICAgICBxdWV1ZUl0ZW0sXG4gICAgICAgICAgICAgIHJlcXVlc3RJZCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaGFzSG9va0NvbmZsaWN0IHx8PSByZXN1bHQuaGFzSG9va0NvbmZsaWN0O1xuICAgICAgICAgICAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbiB8fD0gcmVzdWx0Lmhhc0F3YWl0ZWRIb29rQ3JlYXRpb247XG4gICAgICAgICAgICBjcmVhdGlvbkNvbmZsaWN0ZWQgPSByZXN1bHQuaGFzSG9va0NvbmZsaWN0O1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIERpc3Bvc2UgYWZ0ZXIgY3JlYXRpb24gZm9yIGhvb2tzIGJvcm4gYW5kIGRpc3Bvc2VkIHdpdGhpbiB0aGlzXG4gICAgICAgICAgLy8gYmF0Y2guIEEgaG9vayB3aG9zZSBjcmVhdGlvbiBjb25mbGljdGVkIHdhcyBuZXZlciBjcmVhdGVkLCBzb1xuICAgICAgICAgIC8vIHRoZXJlIGlzIG5vdGhpbmcgdG8gZGlzcG9zZS5cbiAgICAgICAgICBpZiAocXVldWVJdGVtLmRpc3Bvc2VkICYmICFjcmVhdGlvbkNvbmZsaWN0ZWQpIHtcbiAgICAgICAgICAgIGF3YWl0IGRpc3Bvc2VIb29rKHF1ZXVlSXRlbSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KVxuICAgICk7XG4gICAgaG9va0NyZWF0aW9uTXMgPSBEYXRlLm5vdygpIC0gaG9va1BoYXNlU3RhcnQ7XG4gIH1cblxuICAvLyBQcm9jZXNzIGFib3J0IHJlcXVlc3RzIOKAlCByZXN1bWUgdGhlIGhvb2sgd2l0aCBhYm9ydCBwYXlsb2FkIGFuZCB3cml0ZSBzdHJlYW0gcGFja2V0XG4gIGNvbnN0IGhvb2tzTmVlZGluZ0Fib3J0ID0gYWxsSG9va0l0ZW1zLmZpbHRlcihcbiAgICAoaXRlbSkgPT4gaXRlbS5hYm9ydFJlcXVlc3RlZCAmJiAhaXRlbS5kaXNwb3NlZFxuICApO1xuXG4gIGlmIChob29rc05lZWRpbmdBYm9ydC5sZW5ndGggPiAwKSB7XG4gICAgYXdhaXQgZW5zdXJlUnVuUmVhZHkoKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIGhvb2tzTmVlZGluZ0Fib3J0Lm1hcChhc3luYyAocXVldWVJdGVtKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgLy8gRGVoeWRyYXRlIHRoZSBhYm9ydCBwYXlsb2FkIGZvciBzdG9yYWdlXG4gICAgICAgICAgY29uc3QgYWJvcnRQYXlsb2FkID0gYXdhaXQgZGVoeWRyYXRlU3RlcEFyZ3VtZW50cyhcbiAgICAgICAgICAgIHsgYWJvcnRlZDogdHJ1ZSwgcmVhc29uOiBxdWV1ZUl0ZW0uYWJvcnRSZWFzb24gfSxcbiAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgZW5jcnlwdGlvbktleSxcbiAgICAgICAgICAgIHN1c3BlbnNpb24uZ2xvYmFsVGhpcyxcbiAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgY29tcHJlc3Npb25cbiAgICAgICAgICApO1xuXG4gICAgICAgICAgLy8gQ3JlYXRlIGhvb2tfcmVjZWl2ZWQgZXZlbnQgd2l0aCBhYm9ydCBwYXlsb2FkXG4gICAgICAgICAgYXdhaXQgd29ybGQuZXZlbnRzLmNyZWF0ZShydW5JZCwge1xuICAgICAgICAgICAgZXZlbnRUeXBlOiAnaG9va19yZWNlaXZlZCcgYXMgY29uc3QsXG4gICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICB0b2tlbjogcXVldWVJdGVtLnRva2VuLFxuICAgICAgICAgICAgICBwYXlsb2FkOiBhYm9ydFBheWxvYWQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgLy8gV3JpdGUgc3RyZWFtIGNhbmNlbGxhdGlvbiBwYWNrZXQgZm9yIHJlYWwtdGltZSBzdGVwIHByb3BhZ2F0aW9uLlxuICAgICAgICAgIC8vIFJldXNlIHRoZSBzYW1lIGRlaHlkcmF0ZWQgcGF5bG9hZCBhcyB0aGUgaG9vayBldmVudCBzbyB0aGUgcmVhc29uXG4gICAgICAgICAgLy8gcm91bmQtdHJpcHMgdGhyb3VnaCBgZGVoeWRyYXRlU3RlcEFyZ3VtZW50c2AgLyBgaHlkcmF0ZVN0ZXBBcmd1bWVudHNgXG4gICAgICAgICAgLy8gKGhhbmRsZXMgRE9NRXhjZXB0aW9uLCBjdXN0b20gZXJyb3JzLCBlbmNyeXB0aW9uLCBldGMuKSBpbnN0ZWFkIG9mXG4gICAgICAgICAgLy8gYmFyZSBKU09OLnN0cmluZ2lmeSB3aGljaCBsb3NlcyB0eXBlIGluZm9ybWF0aW9uIGFuZCBkcm9wcyB1bmRlZmluZWQuXG4gICAgICAgICAgLy8gc3RyZWFtTmFtZSBpcyBzZXQgb24gdGhlIHF1ZXVlIGl0ZW0gYXQgY29udHJvbGxlciBjb25zdHJ1Y3Rpb24gdGltZVxuICAgICAgICAgIC8vIChzZWUgd29ya2Zsb3cvYWJvcnQtY29udHJvbGxlci50cykuXG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHN0cmVhbU5hbWUgPSBnZXRBYm9ydFN0cmVhbUlkRnJvbVRva2VuKHF1ZXVlSXRlbS50b2tlbik7XG4gICAgICAgICAgICBhd2FpdCB3b3JsZC5zdHJlYW1zLndyaXRlKFxuICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgc3RyZWFtTmFtZSxcbiAgICAgICAgICAgICAgYWJvcnRQYXlsb2FkIGFzIFVpbnQ4QXJyYXlcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBhd2FpdCB3b3JsZC5zdHJlYW1zLmNsb3NlKHJ1bklkLCBzdHJlYW1OYW1lKTtcbiAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIC8vIEJlc3QtZWZmb3J0IHN0cmVhbSB3cml0ZSDigJQgaG9vayBldmVudCBwcm92aWRlcyB0aGUgZHVyYWJsZSBmYWxsYmFja1xuICAgICAgICAgICAgcnVudGltZUxvZ2dlci5kZWJ1ZyhcbiAgICAgICAgICAgICAgJ0ZhaWxlZCB0byB3cml0ZSBhYm9ydCBzdHJlYW0gcGFja2V0LCBob29rIGV2ZW50IHdpbGwgcHJvdmlkZSBmYWxsYmFjaycsXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikgfHwgUnVuRXhwaXJlZEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgJ1dvcmtmbG93IHJ1biBhbHJlYWR5IGNvbXBsZXRlZCwgc2tpcHBpbmcgYWJvcnQnLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIC8vIENyZWF0ZSBzdGVwIGV2ZW50cyBmb3Igc3RlcHMgdGhhdCBkb24ndCBoYXZlIHRoZW0geWV0LlxuICAvLyBVbmxpa2UgVjEsIHdlIGRvIE5PVCBxdWV1ZSBzdGVwIG1lc3NhZ2VzIGZyb20gaGVyZSDigJQgdGhlIGNhbGxlclxuICAvLyBkZWNpZGVzIHdoaWNoIHN0ZXBzIHRvIGV4ZWN1dGUgaW5saW5lIHZzLiBxdWV1ZSB0byBiYWNrZ3JvdW5kLlxuICAvLyBXYWl0IGV2ZW50cyBhcmUgYWxzbyBjcmVhdGVkIGluIHBhcmFsbGVsIGJlbG93LlxuICBjb25zdCBzdGVwc05lZWRpbmdDcmVhdGlvbiA9IG5ldyBTZXQoXG4gICAgc3RlcEl0ZW1zXG4gICAgICAuZmlsdGVyKChxdWV1ZUl0ZW0pID0+ICFxdWV1ZUl0ZW0uaGFzQ3JlYXRlZEV2ZW50KVxuICAgICAgLm1hcCgocXVldWVJdGVtKSA9PiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZClcbiAgKTtcblxuICAvLyBDb3JyZWxhdGlvbiBJRHMgZm9yIHdoaWNoIFRISVMgc3VzcGVuc2lvbiBjYWxsIGFjdHVhbGx5IHdyb3RlIHRoZVxuICAvLyBzdGVwX2NyZWF0ZWQgZXZlbnQuIFBvcHVsYXRlZCBieSB0aGUgb3BzIGJlbG93IGFmdGVyIGEgc3VjY2Vzc2Z1bFxuICAvLyBldmVudHMuY3JlYXRlIOKAlCB1c2VkIGJ5IHRoZSBjYWxsZXIgdG8gY2xhaW0gb3duZXJzaGlwIGFuZCBhdm9pZFxuICAvLyByYWNpbmcgd2l0aCBjb25jdXJyZW50IGhhbmRsZXJzIG9uIHN0ZXAgZXhlY3V0aW9uLlxuICBjb25zdCBjcmVhdGVkU3RlcENvcnJlbGF0aW9uSWRzID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgLy8gTGF6eSBpbmxpbmUgc3RhcnQ6IGRlZmVyIHRoZSBzdGVwX2NyZWF0ZWQgd3JpdGUgZm9yIHVwIHRvXG4gIC8vIGBnZXRNYXhJbmxpbmVTdGVwcygpYCBzdGVwcyB0aGUgY2FsbGVyIHdpbGwgcnVuIGlubGluZSAoaW4gcGFyYWxsZWwpLiBFYWNoXG4gIC8vIHN0ZXAgaXMgY3JlYXRlZCBvbiB0aGUgZmx5IGJ5IHRoZSBsYXp5IGBzdGVwX3N0YXJ0ZWRgIGV4ZWN1dGVTdGVwIHNlbmRzXG4gIC8vIChzYXZpbmcgYSByb3VuZC10cmlwIHBlciBzdGVwKS4gV2UgbmV2ZXIgZGVmZXIgd2hlbiBhIGBob29rLmdldENvbmZsaWN0KClgXG4gIC8vIGF3YWl0ZXIgaXMgcHJlc2VudCwgYmVjYXVzZSBpbiB0aGF0IGNhc2UgdGhlIGNhbGxlciBleGVjdXRlcyBub3RoaW5nIGlubGluZVxuICAvLyAoaXQgcmUtaW52b2tlcyBpbW1lZGlhdGVseSB0byByZXNvbHZlIHRoZSBhd2FpdGVyKSwgc28gZGVmZXJyaW5nIHdvdWxkXG4gIC8vIGxlYXZlIHRoZSBzdGVwcyB1bmNyZWF0ZWQgYW5kIHVucXVldWVkLiBXZSBwaWNrIHRoZSBmaXJzdCBOIHVuY3JlYXRlZCBzdGVwc1xuICAvLyDigJQgbWF0Y2hpbmcgdGhlIGNhbGxlcidzIGlubGluZS1jYW5kaWRhdGUgc2VsZWN0aW9uIOKAlCBhbmQgZGVoeWRyYXRlIHRoZWlyXG4gIC8vIGlucHV0IGhlcmUgc28gZXhlY3V0ZVN0ZXAgY2FuIHNoaXAgaXQgYXMgdGhlIHN0ZXBfc3RhcnRlZCBwYXlsb2FkLlxuICBjb25zdCBsYXp5SW5saW5lQ29ycmVsYXRpb25JZHMgPSBuZXcgU2V0PHN0cmluZz4oXG4gICAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbiA9PT0gZmFsc2VcbiAgICAgID8gc3RlcEl0ZW1zXG4gICAgICAgICAgLmZpbHRlcigoaXRlbSkgPT4gc3RlcHNOZWVkaW5nQ3JlYXRpb24uaGFzKGl0ZW0uY29ycmVsYXRpb25JZCkpXG4gICAgICAgICAgLnNsaWNlKDAsIGdldE1heElubGluZVN0ZXBzKCkpXG4gICAgICAgICAgLm1hcCgoaXRlbSkgPT4gaXRlbS5jb3JyZWxhdGlvbklkKVxuICAgICAgOiBbXVxuICApO1xuICAvLyBDb2xsZWN0ZWQgYnkgY29ycmVsYXRpb25JZCBiZWNhdXNlIHRoZSBwZXItc3RlcCBvcHMgYmVsb3cgcnVuIGNvbmN1cnJlbnRseVxuICAvLyBhbmQgc2V0dGxlIG91dCBvZiBvcmRlci4gV2UgcmVidWlsZCB0aGUgYXJyYXkgaW4gZGV0ZXJtaW5pc3RpY1xuICAvLyBgbGF6eUlubGluZUNvcnJlbGF0aW9uSWRzYCBvcmRlciAodGhlIG9yZGVyZWQgc2xpY2UgYWJvdmUpIGFmdGVyIHRoZSBvcHNcbiAgLy8gc2V0dGxlLCBzbyB0aGUgaW5saW5lIGJhdGNoIG9yZGVyIGlzIHN0YWJsZSByZWdhcmRsZXNzIG9mIGRlaHlkcmF0aW9uIHRpbWluZy5cbiAgY29uc3QgbGF6eUlubGluZUJ5Q29ycmVsYXRpb25JZCA9IG5ldyBNYXA8XG4gICAgc3RyaW5nLFxuICAgIFN1c3BlbnNpb25IYW5kbGVyUmVzdWx0WydsYXp5SW5saW5lU3RlcHMnXVtudW1iZXJdXG4gID4oKTtcblxuICBjb25zdCBvcHM6IFByb21pc2U8dm9pZD5bXSA9IFtdO1xuXG4gIC8vIFN0ZXBzOiBjcmVhdGUgc3RlcF9jcmVhdGVkIGV2ZW50cyAobm8gcXVldWluZyDigJQgVjIgcmV0dXJucyBwZW5kaW5nIHN0ZXBzIHRvIGNhbGxlcilcbiAgZm9yIChjb25zdCBxdWV1ZUl0ZW0gb2Ygc3RlcEl0ZW1zKSB7XG4gICAgaWYgKHN0ZXBzTmVlZGluZ0NyZWF0aW9uLmhhcyhxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCkpIHtcbiAgICAgIG9wcy5wdXNoKFxuICAgICAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IGRlaHlkcmF0ZWRJbnB1dCA9IGF3YWl0IGRlaHlkcmF0ZVN0ZXBBcmd1bWVudHMoXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGFyZ3M6IHF1ZXVlSXRlbS5hcmdzLFxuICAgICAgICAgICAgICBjbG9zdXJlVmFyczogcXVldWVJdGVtLmNsb3N1cmVWYXJzLFxuICAgICAgICAgICAgICB0aGlzVmFsOiBxdWV1ZUl0ZW0udGhpc1ZhbCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgIGVuY3J5cHRpb25LZXksXG4gICAgICAgICAgICBzdXNwZW5zaW9uLmdsb2JhbFRoaXMsXG4gICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgIGNvbXByZXNzaW9uXG4gICAgICAgICAgKTtcbiAgICAgICAgICAvLyBEZWZlcnJlZCAobGF6eSkgaW5saW5lIHN0ZXA6IHNraXAgdGhlIHN0ZXBfY3JlYXRlZCB3cml0ZSDigJQgdGhlXG4gICAgICAgICAgLy8gY2FsbGVyJ3MgaW5saW5lIGV4ZWN1dGVTdGVwIHdpbGwgc2VuZCBhIGxhenkgc3RlcF9zdGFydGVkIGNhcnJ5aW5nXG4gICAgICAgICAgLy8gdGhpcyBpbnB1dCwgYW5kIHRoZSB3b3JsZCBjcmVhdGVzIHRoZSBzdGVwIChlbnRpdHkgKyBzeW50aGV0aWNcbiAgICAgICAgICAvLyBzdGVwX2NyZWF0ZWQgZXZlbnQpIGF0b21pY2FsbHkuIFdlIGRvIE5PVCBhZGQgaXQgdG9cbiAgICAgICAgICAvLyBjcmVhdGVkU3RlcENvcnJlbGF0aW9uSWRzOyBvd25lcnNoaXAgaXMgZGVjaWRlZCBieSB0aGF0IGxhenlcbiAgICAgICAgICAvLyBzdGVwX3N0YXJ0ZWQncyBhdG9taWMgY3JlYXRlLWNsYWltIGluc3RlYWQuXG4gICAgICAgICAgaWYgKGxhenlJbmxpbmVDb3JyZWxhdGlvbklkcy5oYXMocXVldWVJdGVtLmNvcnJlbGF0aW9uSWQpKSB7XG4gICAgICAgICAgICBsYXp5SW5saW5lQnlDb3JyZWxhdGlvbklkLnNldChxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCwge1xuICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgc3RlcE5hbWU6IHF1ZXVlSXRlbS5zdGVwTmFtZSxcbiAgICAgICAgICAgICAgZGVoeWRyYXRlZElucHV0OiBkZWh5ZHJhdGVkSW5wdXQgYXMgU2VyaWFsaXplZERhdGEsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3Qgc3RlcEV2ZW50OiBDcmVhdGVFdmVudFJlcXVlc3QgPSB7XG4gICAgICAgICAgICBldmVudFR5cGU6ICdzdGVwX2NyZWF0ZWQnIGFzIGNvbnN0LFxuICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgc3RlcE5hbWU6IHF1ZXVlSXRlbS5zdGVwTmFtZSxcbiAgICAgICAgICAgICAgd29ya2Zsb3dOYW1lOiBydW4ud29ya2Zsb3dOYW1lLFxuICAgICAgICAgICAgICBpbnB1dDogZGVoeWRyYXRlZElucHV0IGFzIFNlcmlhbGl6ZWREYXRhLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9O1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBlbnN1cmVSdW5SZWFkeSgpO1xuICAgICAgICAgICAgYXdhaXQgd29ybGQuZXZlbnRzLmNyZWF0ZShydW5JZCwgc3RlcEV2ZW50LCB7IHJlcXVlc3RJZCB9KTtcbiAgICAgICAgICAgIGNyZWF0ZWRTdGVwQ29ycmVsYXRpb25JZHMuYWRkKHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKTtcbiAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKCdTdGVwIGFscmVhZHkgZXhpc3RzLCBjb250aW51aW5nJywge1xuICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pKClcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLy8gQ3JlYXRlIHdhaXQgZXZlbnRzIChzYW1lIGFzIFYxKVxuICBmb3IgKGNvbnN0IHF1ZXVlSXRlbSBvZiB3YWl0SXRlbXMpIHtcbiAgICBpZiAoIXF1ZXVlSXRlbS5oYXNDcmVhdGVkRXZlbnQpIHtcbiAgICAgIG9wcy5wdXNoKFxuICAgICAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHdhaXRFdmVudDogQ3JlYXRlRXZlbnRSZXF1ZXN0ID0ge1xuICAgICAgICAgICAgZXZlbnRUeXBlOiAnd2FpdF9jcmVhdGVkJyBhcyBjb25zdCxcbiAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgIHJlc3VtZUF0OiBxdWV1ZUl0ZW0ucmVzdW1lQXQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH07XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IGVuc3VyZVJ1blJlYWR5KCk7XG4gICAgICAgICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKHJ1bklkLCB3YWl0RXZlbnQsIHsgcmVxdWVzdElkIH0pO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ1dhaXQgYWxyZWFkeSBleGlzdHMsIGNvbnRpbnVpbmcnLCB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSkoKVxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBmb3IgKGNvbnN0IHF1ZXVlSXRlbSBvZiBhdHRyaWJ1dGVJdGVtcykge1xuICAgIG9wcy5wdXNoKFxuICAgICAgKGFzeW5jICgpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCBlbnN1cmVSdW5SZWFkeSgpO1xuICAgICAgICAgIGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUoXG4gICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZXZlbnRUeXBlOiAnYXR0cl9zZXQnLFxuICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgICBjaGFuZ2VzOiBxdWV1ZUl0ZW0uY2hhbmdlcyxcbiAgICAgICAgICAgICAgICB3cml0ZXI6IHsgdHlwZTogJ3dvcmtmbG93JyB9LFxuICAgICAgICAgICAgICAgIC4uLihxdWV1ZUl0ZW0uYWxsb3dSZXNlcnZlZEF0dHJpYnV0ZXNcbiAgICAgICAgICAgICAgICAgID8geyBhbGxvd1Jlc2VydmVkQXR0cmlidXRlczogdHJ1ZSB9XG4gICAgICAgICAgICAgICAgICA6IHt9KSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7IHJlcXVlc3RJZCB9XG4gICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAnV29ya2Zsb3cgYXR0cmlidXRlIGV2ZW50IGFscmVhZHkgZXhpc3RzLCBjb250aW51aW5nJyxcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0gZWxzZSBpZiAoaXNBdHRyaWJ1dGVWYWxpZGF0aW9uRmFpbHVyZShlcnIpKSB7XG4gICAgICAgICAgICAvLyBEZXRlcm1pbmlzdGljIHZhbGlkYXRpb24gcmVqZWN0aW9uIGZyb20gdGhlIFdvcmxkIOKAlCBlLmcuIHRoZVxuICAgICAgICAgICAgLy8gY3VtdWxhdGl2ZSBwZXItcnVuIGF0dHJpYnV0ZSBjYXAsIHdoaWNoIG9ubHkgdGhlIFdvcmxkIGNhblxuICAgICAgICAgICAgLy8gY2hlY2sgYWdhaW5zdCB0aGUgcnVuJ3MgZXhpc3RpbmcgYXR0cmlidXRlcy4gUmVkZWxpdmVyaW5nIHRoZVxuICAgICAgICAgICAgLy8gb3JjaGVzdHJhdG9yIG1lc3NhZ2UgcmVwbGF5cyB0aGUgd29ya2Zsb3cgaW50byB0aGUgZXhhY3Qgc2FtZVxuICAgICAgICAgICAgLy8gd3JpdGUgYW5kIHRoZSBleGFjdCBzYW1lIHJlamVjdGlvbiwgc28gcmV0cnlpbmcgY2FuIG5ldmVyXG4gICAgICAgICAgICAvLyBzdWNjZWVkLiBTdXJmYWNlIGl0IGFzIGEgRmF0YWxFcnJvciBzbyB0aGUgY2FsbGVyIGZhaWxzIHRoZVxuICAgICAgICAgICAgLy8gcnVuIHdpdGggYSBjbGVhciBlcnJvciBpbnN0ZWFkIG9mIHdlZGdpbmcgaXQgaW4gcmVkZWxpdmVyeS5cbiAgICAgICAgICAgIGNvbnN0IGZhdGFsID0gbmV3IEZhdGFsRXJyb3IoXG4gICAgICAgICAgICAgIGBzZXRBdHRyaWJ1dGVzIGZhaWxlZCBXb3JsZCB2YWxpZGF0aW9uOiAke1xuICAgICAgICAgICAgICAgIGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKVxuICAgICAgICAgICAgICB9YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGZhdGFsLmNhdXNlID0gZXJyO1xuICAgICAgICAgICAgdGhyb3cgZmF0YWw7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pKClcbiAgICApO1xuICB9XG5cbiAgLy8gQXdhaXQgdGhlIHN0ZXBfY3JlYXRlZCAvIHdhaXRfY3JlYXRlZCBldmVudCBjcmVhdGVzIGJlZm9yZSByZXR1cm5pbmcuXG4gIC8vIFRoZSBjYWxsZXIgKHdvcmtmbG93RW50cnlwb2ludCkgb25seSBlbnF1ZXVlcyB0aGUgc3RlcC1kaXNwYXRjaCBxdWV1ZVxuICAvLyBtZXNzYWdlcyBBRlRFUiBoYW5kbGVTdXNwZW5zaW9uIHJlc29sdmVzLCBhbmQgdGhlIHF1ZXVlIGhhbmRsZXIgYWNrc1xuICAvLyB0aGUgb3JjaGVzdHJhdG9yIG1lc3NhZ2Ugb25seSBhZnRlciB0aGUgY2FsbGVyIHJlc29sdmVzLiBTbyB0aGUgc3RlcF9jcmVhdGVkXG4gIC8vIGV2ZW50cyBtdXN0IGJlIGR1cmFibGUgaGVyZSwgYW5kIHRoZSBkaXNwYXRjaCBzZW5kcyBtdXN0IGNvbXBsZXRlIGluIHRoZSBjYWxsZXIsXG4gIC8vIGFsbCBiZWZvcmUgYWNrLiBJZiB0aGUgcHJvY2VzcyBjcmFzaGVzIGJlZm9yZSB0aGlzIHJlc29sdmVzLCB0aGUgb3JjaGVzdHJhdG9yXG4gIC8vIG1lc3NhZ2UgaXMgbm90IGFja2VkIGFuZCBWUVMgcmVkZWxpdmVycywgcmUtY3JlYXRlcyB0aGUgKGlkZW1wb3RlbnQpXG4gIC8vIHN0ZXBfY3JlYXRlZCBhbmQgcmUtZGlzcGF0Y2hlcywgYW5kIHJlY292ZXJzIHRoZSBydW4gaW5zdGVhZCBvZiBvcnBoYW5pbmcgaXQuXG4gIGF3YWl0IFByb21pc2UuYWxsKG9wcyk7XG5cbiAgLy8gUmVidWlsZCB0aGUgaW5saW5lIGJhdGNoIGluIGRldGVybWluaXN0aWMgb3JkZXIuIGBsYXp5SW5saW5lQ29ycmVsYXRpb25JZHNgXG4gIC8vIGlzIGEgU2V0IHNlZWRlZCBmcm9tIHRoZSBvcmRlcmVkIGZpcnN0LU4gc2xpY2UsIHNvIGl0ZXJhdGluZyBpdCBwcmVzZXJ2ZXNcbiAgLy8gc3RlcEl0ZW1zIG9yZGVyOyBldmVyeSBpZCBpbiBpdCB3YXMgc2V0IGJ5IHRoZSBsYXp5IGJyYW5jaCBhYm92ZS5cbiAgY29uc3QgbGF6eUlubGluZVN0ZXBzOiBTdXNwZW5zaW9uSGFuZGxlclJlc3VsdFsnbGF6eUlubGluZVN0ZXBzJ10gPSBbXTtcbiAgZm9yIChjb25zdCBjb3JyZWxhdGlvbklkIG9mIGxhenlJbmxpbmVDb3JyZWxhdGlvbklkcykge1xuICAgIGNvbnN0IGxhenlTdGVwID0gbGF6eUlubGluZUJ5Q29ycmVsYXRpb25JZC5nZXQoY29ycmVsYXRpb25JZCk7XG4gICAgaWYgKGxhenlTdGVwKSBsYXp5SW5saW5lU3RlcHMucHVzaChsYXp5U3RlcCk7XG4gIH1cblxuICAvLyBGaW5kIHRoZSBzb29uZXN0IHBlbmRpbmcgd2FpdCAobWluaW11bSB0aW1lb3V0KVxuICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICBsZXQgc29vbmVzdFdhaXQ6IHsgc2Vjb25kczogbnVtYmVyOyBjb3JyZWxhdGlvbklkOiBzdHJpbmcgfSB8IHVuZGVmaW5lZDtcbiAgZm9yIChjb25zdCBxdWV1ZUl0ZW0gb2Ygd2FpdEl0ZW1zKSB7XG4gICAgY29uc3QgcmVzdW1lQXRNcyA9IHF1ZXVlSXRlbS5yZXN1bWVBdC5nZXRUaW1lKCk7XG4gICAgY29uc3QgZGVsYXlNcyA9IE1hdGgubWF4KDEwMDAsIHJlc3VtZUF0TXMgLSBub3cpO1xuICAgIGNvbnN0IHRpbWVvdXRTZWNvbmRzID0gTWF0aC5jZWlsKGRlbGF5TXMgLyAxMDAwKTtcbiAgICBpZiAoIXNvb25lc3RXYWl0IHx8IHRpbWVvdXRTZWNvbmRzIDwgc29vbmVzdFdhaXQuc2Vjb25kcykge1xuICAgICAgc29vbmVzdFdhaXQgPSB7XG4gICAgICAgIHNlY29uZHM6IHRpbWVvdXRTZWNvbmRzLFxuICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgLi4uQXR0cmlidXRlLldvcmtmbG93UnVuU3RhdHVzKCd3b3JrZmxvd19zdXNwZW5kZWQnKSxcbiAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dTdGVwc0NyZWF0ZWQoc3RlcEl0ZW1zLmxlbmd0aCksXG4gICAgLi4uQXR0cmlidXRlLldvcmtmbG93SG9va3NDcmVhdGVkKGhvb2tzTmVlZGluZ0NyZWF0aW9uLmxlbmd0aCksXG4gICAgLi4uQXR0cmlidXRlLldvcmtmbG93V2FpdHNDcmVhdGVkKHdhaXRJdGVtcy5sZW5ndGgpLFxuICB9KTtcblxuICByZXR1cm4ge1xuICAgIHBlbmRpbmdTdGVwczogc3RlcEl0ZW1zLFxuICAgIGNyZWF0ZWRTdGVwQ29ycmVsYXRpb25JZHMsXG4gICAgbGF6eUlubGluZVN0ZXBzLFxuICAgIC8vIE9uIGhvb2sgY29uZmxpY3QgdGhlIGNhbGxlciByZS1pbnZva2VzIGltbWVkaWF0ZWx5IGFuZCBuZXZlciByZWFkc1xuICAgIC8vIHRoZSB3YWl0IHRpbWVvdXQsIHNvIGRvbid0IHJlcG9ydCBvbmUuXG4gICAgd2FpdFRpbWVvdXQ6IGhhc0hvb2tDb25mbGljdCA/IHVuZGVmaW5lZCA6IHNvb25lc3RXYWl0LFxuICAgIGhhc0hvb2tDb25mbGljdCxcbiAgICBoYXNBd2FpdGVkSG9va0NyZWF0aW9uLFxuICAgIGhhc0F0dHJpYnV0ZUV2ZW50czogYXR0cmlidXRlSXRlbXMubGVuZ3RoID4gMCxcbiAgICBoYXNIb29rRXZlbnRzOiBob29rc05lZWRpbmdDcmVhdGlvbi5sZW5ndGggPiAwLFxuICAgIGhvb2tDcmVhdGlvbk1zLFxuICB9O1xufVxuXG4vKipcbiAqIFdoZXRoZXIgYW4gYGV2ZW50cy5jcmVhdGVgIHJlamVjdGlvbiBpcyBhIGRldGVybWluaXN0aWMgYXR0cmlidXRlXG4gKiB2YWxpZGF0aW9uIGZhaWx1cmUgcmF0aGVyIHRoYW4gYSB0cmFuc2llbnQvc3RvcmFnZSBlcnJvci4gTG9jYWwgV29ybGRzXG4gKiAod29ybGQtbG9jYWwsIHdvcmxkLXBvc3RncmVzKSB0aHJvdyBgQXR0cmlidXRlVmFsaWRhdGlvbkVycm9yYCBkaXJlY3RseTtcbiAqIHJlbW90ZSBXb3JsZHMgc3VyZmFjZSB0aGUgZXF1aXZhbGVudCBzZXJ2ZXItc2lkZSByZWplY3Rpb24gYXMgYVxuICogYFdvcmtmbG93V29ybGRFcnJvcmAgd2l0aCBIVFRQIHN0YXR1cyA0MDAuIFRoZSBuYW1lIGNoZWNrIGNvdmVyc1xuICogYEF0dHJpYnV0ZVZhbGlkYXRpb25FcnJvcmAgaW5zdGFuY2VzIGZyb20gYSBkaWZmZXJlbnQgY29weSBvZlxuICogYEB3b3JrZmxvdy93b3JsZGAgdGhhbiB0aGUgb25lIHRoaXMgcGFja2FnZSByZXNvbHZlZC5cbiAqL1xuZnVuY3Rpb24gaXNBdHRyaWJ1dGVWYWxpZGF0aW9uRmFpbHVyZShlcnI6IHVua25vd24pOiBib29sZWFuIHtcbiAgaWYgKGVyciBpbnN0YW5jZW9mIEF0dHJpYnV0ZVZhbGlkYXRpb25FcnJvcikgcmV0dXJuIHRydWU7XG4gIGlmIChlcnIgaW5zdGFuY2VvZiBFcnJvciAmJiBlcnIubmFtZSA9PT0gJ0F0dHJpYnV0ZVZhbGlkYXRpb25FcnJvcicpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICByZXR1cm4gV29ya2Zsb3dXb3JsZEVycm9yLmlzKGVycikgJiYgZXJyLnN0YXR1cyA9PT0gNDAwO1xufVxuIl19