@workflow/core 5.0.0-beta.1 → 5.0.0-beta.11

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 (215) hide show
  1. package/README.md +1 -1
  2. package/dist/attribute-changes.d.ts +7 -0
  3. package/dist/attribute-changes.d.ts.map +1 -0
  4. package/dist/attribute-changes.js +25 -0
  5. package/dist/capabilities.js +1 -1
  6. package/dist/capture-stack.d.ts +16 -0
  7. package/dist/capture-stack.d.ts.map +1 -0
  8. package/dist/capture-stack.js +21 -0
  9. package/dist/class-serialization.js +1 -1
  10. package/dist/classify-error.d.ts +11 -3
  11. package/dist/classify-error.d.ts.map +1 -1
  12. package/dist/classify-error.js +56 -6
  13. package/dist/context-errors.d.ts +27 -0
  14. package/dist/context-errors.d.ts.map +1 -0
  15. package/dist/context-errors.js +101 -0
  16. package/dist/context-violation-error.d.ts +97 -0
  17. package/dist/context-violation-error.d.ts.map +1 -0
  18. package/dist/context-violation-error.js +147 -0
  19. package/dist/create-hook.d.ts.map +1 -1
  20. package/dist/create-hook.js +4 -3
  21. package/dist/define-hook.d.ts.map +1 -1
  22. package/dist/define-hook.js +20 -5
  23. package/dist/describe-error.d.ts +70 -0
  24. package/dist/describe-error.d.ts.map +1 -0
  25. package/dist/describe-error.js +165 -0
  26. package/dist/encryption.d.ts +22 -1
  27. package/dist/encryption.d.ts.map +1 -1
  28. package/dist/encryption.js +72 -27
  29. package/dist/events-consumer.d.ts +7 -0
  30. package/dist/events-consumer.d.ts.map +1 -1
  31. package/dist/events-consumer.js +18 -3
  32. package/dist/flushable-stream.d.ts +10 -10
  33. package/dist/flushable-stream.d.ts.map +1 -1
  34. package/dist/flushable-stream.js +18 -13
  35. package/dist/global.d.ts +4 -0
  36. package/dist/global.d.ts.map +1 -1
  37. package/dist/global.js +8 -2
  38. package/dist/index.d.ts +1 -0
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +2 -1
  41. package/dist/log-format.d.ts +25 -0
  42. package/dist/log-format.d.ts.map +1 -0
  43. package/dist/log-format.js +250 -0
  44. package/dist/logger.d.ts +28 -30
  45. package/dist/logger.d.ts.map +1 -1
  46. package/dist/logger.js +77 -31
  47. package/dist/private.js +3 -3
  48. package/dist/runtime/constants.d.ts +48 -0
  49. package/dist/runtime/constants.d.ts.map +1 -1
  50. package/dist/runtime/constants.js +91 -8
  51. package/dist/runtime/get-port-lazy.d.ts +10 -0
  52. package/dist/runtime/get-port-lazy.d.ts.map +1 -0
  53. package/dist/runtime/get-port-lazy.js +30 -0
  54. package/dist/runtime/get-world-lazy.d.ts +32 -0
  55. package/dist/runtime/get-world-lazy.d.ts.map +1 -0
  56. package/dist/runtime/get-world-lazy.js +56 -0
  57. package/dist/runtime/helpers.d.ts +38 -5
  58. package/dist/runtime/helpers.d.ts.map +1 -1
  59. package/dist/runtime/helpers.js +141 -25
  60. package/dist/runtime/replay-budget.d.ts +98 -0
  61. package/dist/runtime/replay-budget.d.ts.map +1 -0
  62. package/dist/runtime/replay-budget.js +191 -0
  63. package/dist/runtime/resume-hook.d.ts.map +1 -1
  64. package/dist/runtime/resume-hook.js +5 -4
  65. package/dist/runtime/run.d.ts.map +1 -1
  66. package/dist/runtime/run.js +31 -6
  67. package/dist/runtime/runs.d.ts.map +1 -1
  68. package/dist/runtime/runs.js +4 -1
  69. package/dist/runtime/start.js +9 -4
  70. package/dist/runtime/step-executor.d.ts +42 -0
  71. package/dist/runtime/step-executor.d.ts.map +1 -0
  72. package/dist/runtime/step-executor.js +493 -0
  73. package/dist/runtime/step-handler.d.ts.map +1 -1
  74. package/dist/runtime/step-handler.js +217 -115
  75. package/dist/runtime/suspension-handler.d.ts +22 -4
  76. package/dist/runtime/suspension-handler.d.ts.map +1 -1
  77. package/dist/runtime/suspension-handler.js +90 -73
  78. package/dist/runtime/world-init.d.ts +75 -0
  79. package/dist/runtime/world-init.d.ts.map +1 -0
  80. package/dist/runtime/world-init.js +75 -0
  81. package/dist/runtime/world.d.ts.map +1 -1
  82. package/dist/runtime/world.js +47 -18
  83. package/dist/runtime.d.ts +8 -7
  84. package/dist/runtime.d.ts.map +1 -1
  85. package/dist/runtime.js +802 -320
  86. package/dist/schemas.d.ts +1 -1
  87. package/dist/schemas.d.ts.map +1 -1
  88. package/dist/schemas.js +1 -1
  89. package/dist/serialization/client.d.ts +17 -0
  90. package/dist/serialization/client.d.ts.map +1 -0
  91. package/dist/serialization/client.js +45 -0
  92. package/dist/serialization/codec-devalue.d.ts +14 -0
  93. package/dist/serialization/codec-devalue.d.ts.map +1 -0
  94. package/dist/serialization/codec-devalue.js +98 -0
  95. package/dist/serialization/codec.d.ts +90 -0
  96. package/dist/serialization/codec.d.ts.map +1 -0
  97. package/dist/serialization/codec.js +17 -0
  98. package/dist/serialization/encryption.d.ts +32 -0
  99. package/dist/serialization/encryption.d.ts.map +1 -0
  100. package/dist/serialization/encryption.js +67 -0
  101. package/dist/serialization/errors.d.ts +34 -0
  102. package/dist/serialization/errors.d.ts.map +1 -0
  103. package/dist/serialization/errors.js +59 -0
  104. package/dist/serialization/format.d.ts +60 -0
  105. package/dist/serialization/format.d.ts.map +1 -0
  106. package/dist/serialization/format.js +97 -0
  107. package/dist/serialization/index.d.ts +18 -0
  108. package/dist/serialization/index.d.ts.map +1 -0
  109. package/dist/serialization/index.js +20 -0
  110. package/dist/serialization/reducers/class.d.ts +11 -0
  111. package/dist/serialization/reducers/class.d.ts.map +1 -0
  112. package/dist/serialization/reducers/class.js +68 -0
  113. package/dist/serialization/reducers/common.d.ts +16 -0
  114. package/dist/serialization/reducers/common.d.ts.map +1 -0
  115. package/dist/serialization/reducers/common.js +417 -0
  116. package/dist/serialization/reducers/step-function.d.ts +35 -0
  117. package/dist/serialization/reducers/step-function.d.ts.map +1 -0
  118. package/dist/serialization/reducers/step-function.js +88 -0
  119. package/dist/serialization/step.d.ts +17 -0
  120. package/dist/serialization/step.d.ts.map +1 -0
  121. package/dist/serialization/step.js +45 -0
  122. package/dist/serialization/types.d.ts +228 -0
  123. package/dist/serialization/types.d.ts.map +1 -0
  124. package/dist/serialization/types.js +21 -0
  125. package/dist/serialization/workflow.d.ts +29 -0
  126. package/dist/serialization/workflow.d.ts.map +1 -0
  127. package/dist/serialization/workflow.js +54 -0
  128. package/dist/serialization-format.d.ts +16 -2
  129. package/dist/serialization-format.d.ts.map +1 -1
  130. package/dist/serialization-format.js +103 -5
  131. package/dist/serialization.d.ts +217 -226
  132. package/dist/serialization.d.ts.map +1 -1
  133. package/dist/serialization.js +956 -645
  134. package/dist/set-attributes.d.ts +13 -0
  135. package/dist/set-attributes.d.ts.map +1 -0
  136. package/dist/set-attributes.js +40 -0
  137. package/dist/sleep.d.ts.map +1 -1
  138. package/dist/sleep.js +3 -2
  139. package/dist/source-map.d.ts.map +1 -1
  140. package/dist/source-map.js +44 -6
  141. package/dist/step/context-storage.d.ts +16 -0
  142. package/dist/step/context-storage.d.ts.map +1 -1
  143. package/dist/step/context-storage.js +1 -1
  144. package/dist/step/get-closure-vars.d.ts.map +1 -1
  145. package/dist/step/get-closure-vars.js +3 -2
  146. package/dist/step/get-step-metadata.d.ts.map +1 -1
  147. package/dist/step/get-step-metadata.js +3 -2
  148. package/dist/step/get-workflow-metadata.d.ts.map +1 -1
  149. package/dist/step/get-workflow-metadata.js +3 -2
  150. package/dist/step/writable-stream.d.ts.map +1 -1
  151. package/dist/step/writable-stream.js +44 -4
  152. package/dist/step.d.ts.map +1 -1
  153. package/dist/step.js +97 -19
  154. package/dist/symbols.d.ts +26 -0
  155. package/dist/symbols.d.ts.map +1 -1
  156. package/dist/symbols.js +27 -1
  157. package/dist/telemetry/semantic-conventions.d.ts +2 -2
  158. package/dist/telemetry/semantic-conventions.js +1 -1
  159. package/dist/telemetry.js +1 -1
  160. package/dist/types.d.ts +6 -0
  161. package/dist/types.d.ts.map +1 -1
  162. package/dist/types.js +23 -1
  163. package/dist/util.d.ts +18 -3
  164. package/dist/util.d.ts.map +1 -1
  165. package/dist/util.js +28 -5
  166. package/dist/version.d.ts +1 -1
  167. package/dist/version.d.ts.map +1 -1
  168. package/dist/version.js +2 -2
  169. package/dist/vm/index.d.ts.map +1 -1
  170. package/dist/vm/index.js +3 -2
  171. package/dist/vm/uint8array-base64.js +1 -1
  172. package/dist/vm/uuid.js +1 -1
  173. package/dist/workflow/abort-controller.d.ts +65 -0
  174. package/dist/workflow/abort-controller.d.ts.map +1 -0
  175. package/dist/workflow/abort-controller.js +260 -0
  176. package/dist/workflow/create-hook.d.ts.map +1 -1
  177. package/dist/workflow/create-hook.js +3 -2
  178. package/dist/workflow/define-hook.d.ts +1 -1
  179. package/dist/workflow/define-hook.d.ts.map +1 -1
  180. package/dist/workflow/define-hook.js +8 -4
  181. package/dist/workflow/get-workflow-metadata.d.ts.map +1 -1
  182. package/dist/workflow/get-workflow-metadata.js +14 -3
  183. package/dist/workflow/hook.d.ts.map +1 -1
  184. package/dist/workflow/hook.js +13 -4
  185. package/dist/workflow/index.d.ts +1 -0
  186. package/dist/workflow/index.d.ts.map +1 -1
  187. package/dist/workflow/index.js +5 -3
  188. package/dist/workflow/set-attributes.d.ts +74 -0
  189. package/dist/workflow/set-attributes.d.ts.map +1 -0
  190. package/dist/workflow/set-attributes.js +66 -0
  191. package/dist/workflow/sleep.d.ts.map +1 -1
  192. package/dist/workflow/sleep.js +22 -3
  193. package/dist/workflow/world-init-stub.d.ts +15 -0
  194. package/dist/workflow/world-init-stub.d.ts.map +1 -0
  195. package/dist/workflow/world-init-stub.js +15 -0
  196. package/dist/workflow/writable-stream.js +1 -1
  197. package/dist/workflow.d.ts.map +1 -1
  198. package/dist/workflow.js +83 -31
  199. package/docs/api-reference/create-webhook.mdx +37 -18
  200. package/docs/api-reference/experimental-set-attributes.mdx +63 -0
  201. package/docs/api-reference/get-workflow-metadata.mdx +34 -0
  202. package/docs/api-reference/index.mdx +3 -0
  203. package/docs/foundations/cancellation.mdx +460 -0
  204. package/docs/foundations/errors-and-retries.mdx +7 -3
  205. package/docs/foundations/index.mdx +3 -3
  206. package/docs/foundations/meta.json +3 -2
  207. package/docs/foundations/serialization.mdx +78 -42
  208. package/docs/foundations/starting-workflows.mdx +6 -2
  209. package/docs/foundations/versioning.mdx +263 -0
  210. package/docs/how-it-works/cancellation.mdx +287 -0
  211. package/docs/how-it-works/code-transform.mdx +2 -2
  212. package/docs/how-it-works/event-sourcing.mdx +2 -2
  213. package/docs/how-it-works/meta.json +2 -1
  214. package/package.json +16 -7
  215. package/docs/foundations/common-patterns.mdx +0 -265
package/dist/runtime.js CHANGED
@@ -1,17 +1,21 @@
1
- import { EntityConflictError, RUN_ERROR_CODES, RunExpiredError, WorkflowRuntimeError, } from '@workflow/errors';
1
+ import { types } from 'node:util';
2
+ import { EntityConflictError, FatalError, RUN_ERROR_CODES, RunExpiredError, WorkflowRuntimeError, } from '@workflow/errors';
2
3
  import { parseWorkflowName } from '@workflow/utils/parse-name';
3
4
  import { SPEC_VERSION_CURRENT, WorkflowInvokePayloadSchema, } from '@workflow/world';
4
- import { classifyRunError } from './classify-error.js';
5
- import { importKey } from './encryption.js';
5
+ import { classifyRunError, isWorldContractError } from './classify-error.js';
6
+ import { describeError } from './describe-error.js';
6
7
  import { WorkflowSuspension } from './global.js';
7
8
  import { runtimeLogger } from './logger.js';
8
- import { MAX_QUEUE_DELIVERIES, REPLAY_TIMEOUT_MS, } from './runtime/constants.js';
9
- import { getAllWorkflowRunEvents, getQueueOverhead, handleHealthCheckMessage, parseHealthCheckPayload, withHealthCheck, } from './runtime/helpers.js';
9
+ import { MAX_QUEUE_DELIVERIES } from './runtime/constants.js';
10
+ import { getQueueOverhead, getWorkflowQueueName, handleHealthCheckMessage, loadWorkflowRunEvents, memoizeEncryptionKey, parseHealthCheckPayload, queueMessage, withHealthCheck, } from './runtime/helpers.js';
11
+ import { handleReplayBudgetExhausted, ReplayBudget, } from './runtime/replay-budget.js';
12
+ import { executeStep } from './runtime/step-executor.js';
10
13
  import { handleSuspension } from './runtime/suspension-handler.js';
11
14
  import { getWorld, getWorldHandlers, } from './runtime/world.js';
15
+ import { dehydrateRunError } from './serialization.js';
12
16
  import { remapErrorStack } from './source-map.js';
13
17
  import * as Attribute from './telemetry/semantic-conventions.js';
14
- import { linkToCurrentContext, trace, withTraceContext, withWorkflowBaggage, } from './telemetry.js';
18
+ import { linkToCurrentContext, serializeTraceCarrier, trace, withTraceContext, withWorkflowBaggage, } from './telemetry.js';
15
19
  import { getErrorName, getErrorStack, normalizeUnknownError } from './types.js';
16
20
  import { buildWorkflowSuspensionMessage } from './util.js';
17
21
  import { runWorkflow } from './workflow.js';
@@ -21,17 +25,65 @@ export { getHookByToken, resumeHook, resumeWebhook, } from './runtime/resume-hoo
21
25
  export { getRun, Run, } from './runtime/run.js';
22
26
  export { cancelRun, listStreams, readStream, recreateRunFromExisting, reenqueueRun, wakeUpRun, } from './runtime/runs.js';
23
27
  export { start, } from './runtime/start.js';
24
- export { stepEntrypoint } from './runtime/step-handler.js';
28
+ // V2: stepEntrypoint is no longer re-exported — the combined handler
29
+ // (workflowEntrypoint) executes steps inline. Removing the re-export
30
+ // prevents Turbopack from tracing step-handler.js → get-port.js
31
+ // filesystem operations into the flow route bundle.
25
32
  export { createWorld, getWorld, getWorldHandlers, setWorld, } from './runtime/world.js';
33
+ function getWorkflowSetupErrorCode(err) {
34
+ if (WorkflowRuntimeError.is(err)) {
35
+ return RUN_ERROR_CODES.RUNTIME_ERROR;
36
+ }
37
+ if (isWorldContractError(err)) {
38
+ return RUN_ERROR_CODES.WORLD_CONTRACT_ERROR;
39
+ }
40
+ return null;
41
+ }
42
+ async function recordFatalRunError({ world, workflowRun, runId, requestId, err, errorCode, logMessage, }) {
43
+ runtimeLogger.error(logMessage, {
44
+ workflowRunId: runId,
45
+ errorCode,
46
+ error: err instanceof Error ? err.message : String(err),
47
+ });
48
+ try {
49
+ const getEncryptionKey = memoizeEncryptionKey(world, workflowRun ?? runId);
50
+ await world.events.create(runId, {
51
+ eventType: 'run_failed',
52
+ specVersion: SPEC_VERSION_CURRENT,
53
+ eventData: {
54
+ error: await dehydrateRunError(err, runId, await getEncryptionKey()),
55
+ errorCode,
56
+ },
57
+ }, { requestId });
58
+ }
59
+ catch (failErr) {
60
+ if (EntityConflictError.is(failErr) || RunExpiredError.is(failErr)) {
61
+ return;
62
+ }
63
+ if (isWorldContractError(failErr)) {
64
+ runtimeLogger.error('Fatal world contract error while recording workflow failure', {
65
+ workflowRunId: runId,
66
+ errorCode: RUN_ERROR_CODES.WORLD_CONTRACT_ERROR,
67
+ error: failErr instanceof Error ? failErr.message : String(failErr),
68
+ });
69
+ return;
70
+ }
71
+ throw failErr;
72
+ }
73
+ }
26
74
  /**
27
- * Function that creates a single route which handles any workflow execution
28
- * request and routes to the appropriate workflow function.
75
+ * Creates a single route which handles workflow execution requests,
76
+ * executing steps inline when possible to reduce function invocations
77
+ * and queue overhead.
78
+ *
79
+ * The handler loops: replay workflow → execute step inline → replay → ...
80
+ * until the workflow completes, times out, or encounters non-step suspensions.
29
81
  *
30
- * @param workflowCode - The workflow bundle code containing all the workflow
31
- * functions at the top level.
32
- * @returns A function that can be used as a Vercel API route.
82
+ * @param workflowCode - The workflow bundle code containing all workflow functions
83
+ * @returns A function that can be used as a Vercel API route
33
84
  */
34
85
  export function workflowEntrypoint(workflowCode) {
86
+ const NO_INLINE_REPLAY_AFTER_MS = Number(process.env.WORKFLOW_V2_TIMEOUT_MS) || 120_000;
35
87
  const handler = (worldHandlers) => worldHandlers.createQueueHandler('__wkf_workflow_', async (message_, metadata) => {
36
88
  // Check if this is a health check message
37
89
  // NOTE: Health check messages are intentionally unauthenticated for monitoring purposes.
@@ -42,28 +94,31 @@ export function workflowEntrypoint(workflowCode) {
42
94
  await handleHealthCheckMessage(healthCheck, 'workflow', worldHandlers.specVersion);
43
95
  return;
44
96
  }
45
- const { runId, traceCarrier: traceContext, requestedAt, runInput, } = WorkflowInvokePayloadSchema.parse(message_);
97
+ const { runId, traceCarrier: traceContext, requestedAt, stepId: incomingStepId, stepName: incomingStepName, runInput, } = WorkflowInvokePayloadSchema.parse(message_);
46
98
  const { requestId } = metadata;
47
- // Extract the workflow name from the topic name
48
99
  const workflowName = metadata.queueName.slice('__wkf_workflow_'.length);
49
100
  // --- Max delivery check ---
50
101
  // Enforce max delivery limit before any infrastructure calls.
51
102
  // This prevents runaway workflows from consuming infinite queue deliveries.
52
- // At this point, we want to do the minimal amount of work (no fetching
53
- // of the workflow events, etc. We simply attempt to mark the run as failed
54
- // and if that fails, the message is still consumed but with adequate logging
55
- // that an error occurred preventing us from failing the run.
103
+ // Scoped logger for this run attaches runId/workflowName to every
104
+ // log line and child loggers below, so callers don't repeat it.
105
+ const runLogger = runtimeLogger.forRun(runId, workflowName);
56
106
  if (metadata.attempt > MAX_QUEUE_DELIVERIES) {
57
- runtimeLogger.error(`Workflow handler exceeded max deliveries (${metadata.attempt}/${MAX_QUEUE_DELIVERIES})`, { workflowRunId: runId, workflowName, attempt: metadata.attempt });
107
+ const maxDeliveriesDescription = describeError(undefined, RUN_ERROR_CODES.MAX_DELIVERIES_EXCEEDED);
108
+ runLogger.error(`Workflow handler exceeded max deliveries (${metadata.attempt}/${MAX_QUEUE_DELIVERIES})`, {
109
+ attempt: metadata.attempt,
110
+ errorCode: maxDeliveriesDescription.errorCode,
111
+ errorAttribution: maxDeliveriesDescription.attribution,
112
+ });
58
113
  try {
59
114
  const world = await getWorld();
115
+ const getEncryptionKey = memoizeEncryptionKey(world, runId);
116
+ const err = new FatalError(`Workflow exceeded maximum queue deliveries (${metadata.attempt}/${MAX_QUEUE_DELIVERIES})`);
60
117
  await world.events.create(runId, {
61
118
  eventType: 'run_failed',
62
119
  specVersion: SPEC_VERSION_CURRENT,
63
120
  eventData: {
64
- error: {
65
- message: `Workflow exceeded maximum queue deliveries (${metadata.attempt}/${MAX_QUEUE_DELIVERIES})`,
66
- },
121
+ error: await dehydrateRunError(err, runId, await getEncryptionKey()),
67
122
  errorCode: RUN_ERROR_CODES.MAX_DELIVERIES_EXCEEDED,
68
123
  },
69
124
  }, { requestId });
@@ -73,308 +128,782 @@ export function workflowEntrypoint(workflowCode) {
73
128
  // Run already finished, consume the message silently
74
129
  return;
75
130
  }
76
- runtimeLogger.error(`Failed to mark run as failed after ${metadata.attempt} delivery attempts. ` +
131
+ runLogger.error(`Failed to mark run as failed after ${metadata.attempt} delivery attempts. ` +
77
132
  `A persistent error is preventing the run from being terminated. ` +
78
133
  `The run will remain in its current state until manually resolved. ` +
79
134
  `This is most likely due to a persistent outage of the workflow backend ` +
80
135
  `or a bug in the workflow runtime and should be reported to the Workflow team.`, {
81
- workflowRunId: runId,
82
- error: err instanceof Error ? err.message : String(err),
83
136
  attempt: metadata.attempt,
137
+ errorName: err instanceof Error ? err.name : 'UnknownError',
138
+ errorMessage: err instanceof Error ? err.message : String(err),
139
+ errorStack: err instanceof Error ? err.stack : undefined,
84
140
  });
85
141
  }
86
142
  return;
87
143
  }
88
144
  const spanLinks = await linkToCurrentContext();
89
- // --- Replay timeout guard ---
90
- // If the replay takes longer than the timeout, fail the run and exit.
91
- // This must be lower than the function's maxDuration to ensure
92
- // the failure is recorded before the platform kills the function.
93
- let replayTimeout;
94
- if (process.env.VERCEL_URL !== undefined) {
95
- replayTimeout = setTimeout(async () => {
96
- runtimeLogger.error('Workflow replay exceeded timeout', {
97
- workflowRunId: runId,
98
- timeoutMs: REPLAY_TIMEOUT_MS,
99
- });
100
- try {
101
- const world = await getWorld();
102
- await world.events.create(runId, {
103
- eventType: 'run_failed',
104
- specVersion: SPEC_VERSION_CURRENT,
105
- eventData: {
106
- error: {
107
- message: `Workflow replay exceeded maximum duration (${REPLAY_TIMEOUT_MS / 1000}s)`,
108
- },
109
- errorCode: RUN_ERROR_CODES.REPLAY_TIMEOUT,
110
- },
111
- }, { requestId });
112
- }
113
- catch {
114
- // Best effort — process exits regardless
115
- }
116
- // Note that this also prevents the runtime to acking the queue message,
117
- // so the queue will call back once, after which a 410 will get it to exit early.
118
- process.exit(1);
119
- }, REPLAY_TIMEOUT_MS);
120
- replayTimeout.unref();
121
- }
122
- // Invoke user workflow within the propagated trace context and baggage
145
+ // --- Replay budget bookkeeping ---
146
+ // The replay budget bounds the *non-step* portion of a single
147
+ // handler invocation: deterministic event-log replay, workflow-VM
148
+ // execution between step boundaries, suspension handling, queue
149
+ // round-trips, etc. Inline step bodies (`"use step"` functions
150
+ // invoked via `executeStep`) are intentionally excluded — they are
151
+ // bounded by the platform's function `maxDuration` and the
152
+ // `NO_INLINE_REPLAY_AFTER_MS` early-return guard below.
153
+ //
154
+ // The budget is checked at loop boundaries (top of each `while`
155
+ // iteration). Note this is *less responsive* than the old
156
+ // `setTimeout`-based approach: a single pathological `runWorkflow`
157
+ // call processing a huge event log can overshoot the budget by up
158
+ // to one iteration before bailing. In practice the headroom built
159
+ // into `MAX_REPLAY_TIMEOUT_MS` (and the platform `maxDuration`
160
+ // SIGTERM as ultimate backstop) gives us slack — the previous
161
+ // `setTimeout` approach also relied on the platform kill as the
162
+ // hard backstop. Do *not* "fix" this by adding a `setInterval`;
163
+ // it would risk the same bug we just removed (bounding step
164
+ // bodies).
165
+ //
166
+ // Earlier versions (pre-#2009 fix) used a single `setTimeout`
167
+ // that also bounded step bodies, which broke any workflow with a
168
+ // single step longer than the budget.
169
+ const replayBudget = new ReplayBudget();
123
170
  return await withTraceContext(traceContext, async () => {
124
- // Set workflow context as baggage for automatic propagation
125
171
  return await withWorkflowBaggage({ workflowRunId: runId, workflowName }, async () => {
126
172
  const world = await getWorld();
127
- return trace(`WORKFLOW ${workflowName}`, { links: spanLinks }, async (span) => {
173
+ return trace(`WORKFLOW_V2 ${workflowName}`, { links: spanLinks }, async (span) => {
128
174
  span?.setAttributes({
129
175
  ...Attribute.WorkflowName(workflowName),
130
- ...Attribute.WorkflowOperation('execute'),
131
- // Standard OTEL messaging conventions
176
+ ...Attribute.WorkflowOperation('execute_v2'),
132
177
  ...Attribute.MessagingSystem('vercel-queue'),
133
178
  ...Attribute.MessagingDestinationName(metadata.queueName),
134
179
  ...Attribute.MessagingMessageId(metadata.messageId),
135
180
  ...Attribute.MessagingOperationType('process'),
136
181
  ...getQueueOverhead({ requestedAt }),
137
- });
138
- // TODO: validate `workflowName` exists before consuming message?
139
- span?.setAttributes({
140
182
  ...Attribute.WorkflowRunId(runId),
141
183
  ...Attribute.WorkflowTracePropagated(!!traceContext),
142
184
  });
143
- let workflowStartedAt = -1;
185
+ const invocationStartTime = Date.now();
186
+ let loopIteration = 0;
187
+ // Event cache: keep loaded events in memory across loop iterations.
188
+ // On the first iteration we do a full load; on subsequent iterations
189
+ // we fetch only events created after the last known cursor.
190
+ let cachedEvents = null;
191
+ let eventsCursor = null;
192
+ // Shared state: set by either the background step path
193
+ // or the run_started setup below.
144
194
  let workflowRun;
145
- // Pre-loaded events from the run_started response.
146
- // When present, we skip the events.list call to reduce TTFB.
195
+ let workflowStartedAt = -1;
147
196
  let preloadedEvents;
148
- // --- Infrastructure: prepare the run state ---
149
- // Always call run_started directly this both transitions
150
- // the run to 'running' AND returns the run entity, saving
151
- // a separate runs.get round-trip.
152
- // Contract: events.create('run_started') must be idempotent
153
- // for runs already in 'running' status (return the run
154
- // without error), not just for pending → running transitions.
155
- // Network/server errors propagate to the queue handler for retry.
156
- // WorkflowRuntimeError (data integrity issues) are fatal and
157
- // produce run_failed since retrying won't fix them.
158
- try {
159
- const result = await world.events.create(runId, {
160
- eventType: 'run_started',
161
- // Use the spec version from the original start() call
162
- // when available, so the resilient start path creates
163
- // the run with the correct version (not always current).
164
- specVersion: runInput?.specVersion ?? SPEC_VERSION_CURRENT,
165
- // Pass run input from queue so the server can
166
- // create the run if run_created was missed.
167
- // Uint8Array values survive the queue natively
168
- // (CBOR on world-vercel, JSON reviver on world-local).
169
- ...(runInput
170
- ? {
171
- eventData: {
172
- input: runInput.input,
173
- deploymentId: runInput.deploymentId,
174
- workflowName: runInput.workflowName,
175
- executionContext: runInput.executionContext,
176
- },
177
- }
178
- : {}),
179
- }, { requestId });
180
- if (!result.run) {
181
- throw new WorkflowRuntimeError(`Event creation for 'run_started' did not return the run entity for run "${runId}"`);
182
- }
183
- workflowRun = result.run;
184
- // If the response includes events, use them to skip
185
- // the initial events.list call and reduce TTFB.
186
- if (result.events && result.events.length > 0) {
187
- preloadedEvents = result.events;
188
- }
189
- if (!workflowRun.startedAt) {
190
- throw new WorkflowRuntimeError(`Workflow run "${runId}" has no "startedAt" timestamp`);
191
- }
192
- }
193
- catch (err) {
194
- // Run was concurrently completed/failed/cancelled
195
- if (EntityConflictError.is(err) ||
196
- RunExpiredError.is(err)) {
197
- // EntityConflictError: run was concurrently
198
- // completed/failed/cancelled during setup.
199
- // RunExpiredError: run already in terminal state.
200
- // In both cases, skip processing this message.
201
- runtimeLogger.info('Run already finished during setup, skipping', { workflowRunId: runId, message: err.message });
202
- return;
203
- }
204
- else if (err instanceof WorkflowRuntimeError) {
205
- runtimeLogger.error('Fatal runtime error during workflow setup', { workflowRunId: runId, error: err.message });
197
+ let preloadedEventsCursor;
198
+ // If incoming message has a stepId, this is a background step
199
+ // execution. Execute the step, then check if all parallel steps
200
+ // from the batch are done. If so, replay inline (saving a queue
201
+ // roundtrip). If not, return — the last handler to complete
202
+ // will pick up the replay.
203
+ if (incomingStepId && incomingStepName) {
204
+ try {
205
+ const bgRun = await world.runs.get(runId);
206
+ if (bgRun.status !== 'running') {
207
+ runtimeLogger.debug('Run already finished, skipping background step', { workflowRunId: runId, status: bgRun.status });
208
+ return;
209
+ }
210
+ const bgStartedAt = bgRun.startedAt
211
+ ? +bgRun.startedAt
212
+ : Date.now();
213
+ // Pause the replay budget while the step body runs —
214
+ // step duration is bounded by the platform's function
215
+ // maxDuration, not by the replay timeout. See the
216
+ // ReplayBudget docs for the contract.
217
+ replayBudget.pause();
218
+ let stepResult;
206
219
  try {
207
- await world.events.create(runId, {
208
- eventType: 'run_failed',
209
- specVersion: SPEC_VERSION_CURRENT,
210
- eventData: {
211
- error: {
212
- message: err.message,
213
- stack: err.stack,
214
- },
215
- errorCode: RUN_ERROR_CODES.RUNTIME_ERROR,
216
- },
217
- }, { requestId });
220
+ stepResult = await executeStep({
221
+ world,
222
+ workflowRunId: runId,
223
+ workflowDeploymentId: bgRun.deploymentId,
224
+ workflowName,
225
+ workflowStartedAt: bgStartedAt,
226
+ stepId: incomingStepId,
227
+ stepName: incomingStepName,
228
+ });
229
+ }
230
+ finally {
231
+ replayBudget.resume();
232
+ }
233
+ if (stepResult.type === 'retry') {
234
+ return { timeoutSeconds: stepResult.timeoutSeconds };
235
+ }
236
+ if (stepResult.type === 'throttled') {
237
+ return { timeoutSeconds: stepResult.timeoutSeconds };
238
+ }
239
+ // If step had pending ops (stream writes), break and let
240
+ // waitUntil flush them — can't continue inline.
241
+ if (stepResult.type === 'completed' &&
242
+ stepResult.hasPendingOps) {
243
+ await queueMessage(world, getWorkflowQueueName(workflowName), {
244
+ runId,
245
+ traceCarrier: await serializeTraceCarrier(),
246
+ requestedAt: new Date(),
247
+ });
248
+ return;
218
249
  }
219
- catch (failErr) {
220
- if (EntityConflictError.is(failErr) ||
221
- RunExpiredError.is(failErr)) {
250
+ if (stepResult.type === 'completed' ||
251
+ stepResult.type === 'failed' ||
252
+ stepResult.type === 'skipped') {
253
+ // Load events to check if all parallel steps are done.
254
+ // Use cursor-based loading so the main loop can continue
255
+ // incrementally from here.
256
+ const loaded = await loadWorkflowRunEvents(runId);
257
+ cachedEvents = loaded.events;
258
+ eventsCursor = loaded.cursor;
259
+ // Check for pending steps: any step_created without
260
+ // a matching step_completed or step_failed.
261
+ const stepCreatedIds = new Set();
262
+ const stepTerminalIds = new Set();
263
+ for (const e of cachedEvents) {
264
+ if (e.eventType === 'step_created') {
265
+ stepCreatedIds.add(e.correlationId);
266
+ }
267
+ else if (e.eventType === 'step_completed' ||
268
+ e.eventType === 'step_failed') {
269
+ stepTerminalIds.add(e.correlationId);
270
+ }
271
+ }
272
+ let hasPendingSteps = false;
273
+ for (const id of stepCreatedIds) {
274
+ if (!stepTerminalIds.has(id)) {
275
+ hasPendingSteps = true;
276
+ break;
277
+ }
278
+ }
279
+ if (hasPendingSteps) {
280
+ // Other steps still in progress. Return without
281
+ // queuing — the last handler to complete will see
282
+ // all steps done and replay inline.
283
+ runtimeLogger.debug('Background step done but other steps pending, returning', { workflowRunId: runId });
222
284
  return;
223
285
  }
224
- throw failErr;
286
+ // All steps done — fall through to the main replay loop.
287
+ // Set up shared state so the loop can continue.
288
+ runtimeLogger.debug('All parallel steps done, replaying inline after background step', { workflowRunId: runId });
289
+ workflowRun = bgRun;
290
+ workflowStartedAt = bgStartedAt;
291
+ // cachedEvents and eventsCursor already set from load above
292
+ }
293
+ else {
294
+ return;
225
295
  }
226
- return;
227
296
  }
228
- else {
229
- throw err;
297
+ catch (err) {
298
+ const errorCode = getWorkflowSetupErrorCode(err);
299
+ if (!errorCode) {
300
+ throw err;
301
+ }
302
+ await recordFatalRunError({
303
+ world,
304
+ workflowRun,
305
+ runId,
306
+ requestId,
307
+ err,
308
+ errorCode,
309
+ logMessage: 'Fatal error while preparing background workflow step',
310
+ });
311
+ return;
230
312
  }
231
313
  }
232
- workflowStartedAt = +workflowRun.startedAt;
233
- span?.setAttributes({
234
- ...Attribute.WorkflowRunStatus(workflowRun.status),
235
- ...Attribute.WorkflowStartedAt(workflowStartedAt),
236
- });
237
- if (workflowRun.status !== 'running') {
238
- // Workflow has already completed or failed, so we can skip it
239
- runtimeLogger.info('Workflow already completed or failed, skipping', {
240
- workflowRunId: runId,
241
- status: workflowRun.status,
242
- });
243
- // TODO: for `cancel`, we actually want to propagate a WorkflowCancelled event
244
- // inside the workflow context so the user can gracefully exit. this is SIGTERM
245
- // TODO: furthermore, there should be a timeout or a way to force cancel SIGKILL
246
- // so that we actually exit here without replaying the workflow at all, in the case
247
- // the replaying the workflow is itself failing.
248
- return;
249
- }
250
- // Load all events into memory before running.
251
- // If we got pre-loaded events from the run_started response,
252
- // skip the events.list round-trip to reduce TTFB.
253
- const events = preloadedEvents ??
254
- (await getAllWorkflowRunEvents(workflowRun.runId));
255
- // Check for any elapsed waits and create wait_completed events
256
- const now = Date.now();
257
- // Pre-compute completed correlation IDs for O(n) lookup instead of O(n²)
258
- const completedWaitIds = new Set(events
259
- .filter((e) => e.eventType === 'wait_completed')
260
- .map((e) => e.correlationId));
261
- // Collect all waits that need completion
262
- const waitsToComplete = events
263
- .filter((e) => e.eventType === 'wait_created' &&
264
- e.correlationId !== undefined &&
265
- !completedWaitIds.has(e.correlationId) &&
266
- now >= e.eventData.resumeAt.getTime())
267
- .map((e) => ({
268
- eventType: 'wait_completed',
269
- specVersion: SPEC_VERSION_CURRENT,
270
- correlationId: e.correlationId,
271
- }));
272
- // Create all wait_completed events
273
- for (const waitEvent of waitsToComplete) {
314
+ // --- Infrastructure: prepare the run state ---
315
+ // Skip if workflowRun was already set by the background
316
+ // step path (inline replay after all parallel steps done).
317
+ if (!workflowRun) {
318
+ // Always call run_started directly — this both transitions
319
+ // the run to 'running' AND returns the run entity, saving
320
+ // a separate runs.get round-trip.
321
+ // Contract: events.create('run_started') must be idempotent
322
+ // for runs already in 'running' status (return the run
323
+ // without error), not just for pending → running transitions.
274
324
  try {
275
- const result = await world.events.create(runId, waitEvent, {
276
- requestId,
277
- });
278
- // Add the event to the events array so the workflow can see it
279
- events.push(result.event);
325
+ const result = await world.events.create(runId, {
326
+ eventType: 'run_started',
327
+ // Use the spec version from the original start() call
328
+ // when available, so the resilient start path creates
329
+ // the run with the correct version (not always current).
330
+ specVersion: runInput?.specVersion ?? SPEC_VERSION_CURRENT,
331
+ // Pass run input from queue so the server can
332
+ // create the run if run_created was missed.
333
+ // Uint8Array values survive the queue natively
334
+ // (CBOR on world-vercel, JSON reviver on world-local).
335
+ ...(runInput
336
+ ? {
337
+ eventData: {
338
+ input: runInput.input,
339
+ deploymentId: runInput.deploymentId,
340
+ workflowName: runInput.workflowName,
341
+ executionContext: runInput.executionContext,
342
+ },
343
+ }
344
+ : {}),
345
+ }, { requestId });
346
+ if (!result.run) {
347
+ throw new WorkflowRuntimeError(`Event creation for 'run_started' did not return the run entity for run "${runId}"`);
348
+ }
349
+ workflowRun = result.run;
350
+ // If the response includes events, use them to skip
351
+ // the initial events.list call and reduce TTFB.
352
+ if (result.events &&
353
+ result.events.length > 0 &&
354
+ result.hasMore !== true) {
355
+ preloadedEvents = result.events;
356
+ preloadedEventsCursor = result.cursor;
357
+ }
358
+ if (!workflowRun.startedAt) {
359
+ throw new WorkflowRuntimeError(`Workflow run "${runId}" has no "startedAt" timestamp`);
360
+ }
280
361
  }
281
362
  catch (err) {
282
- if (EntityConflictError.is(err)) {
283
- runtimeLogger.info('Wait already completed, skipping', {
284
- workflowRunId: runId,
285
- correlationId: waitEvent.correlationId,
363
+ // Run was concurrently completed/failed/cancelled
364
+ if (EntityConflictError.is(err) ||
365
+ RunExpiredError.is(err)) {
366
+ // EntityConflictError: run was concurrently
367
+ // completed/failed/cancelled during setup.
368
+ // RunExpiredError: run already in terminal state.
369
+ // In both cases, skip processing this message.
370
+ runtimeLogger.info('Run already finished during setup, skipping', { workflowRunId: runId, message: err.message });
371
+ return;
372
+ }
373
+ else {
374
+ const errorCode = getWorkflowSetupErrorCode(err);
375
+ if (!errorCode) {
376
+ throw err;
377
+ }
378
+ await recordFatalRunError({
379
+ world,
380
+ workflowRun,
381
+ runId,
382
+ requestId,
383
+ err,
384
+ errorCode,
385
+ logMessage: 'Fatal runtime error during workflow setup',
286
386
  });
287
- continue;
387
+ return;
288
388
  }
289
- throw err;
290
389
  }
291
- }
292
- // Resolve the encryption key for this run's deployment
293
- const rawKey = await world.getEncryptionKeyForRun?.(workflowRun);
294
- const encryptionKey = rawKey
295
- ? await importKey(rawKey)
296
- : undefined;
297
- // --- User code execution ---
298
- // Only errors from runWorkflow() (user workflow code) should
299
- // produce run_failed. Infrastructure errors (network, server)
300
- // must propagate to the queue handler for automatic retry.
301
- let workflowResult;
302
- try {
303
- workflowResult = await trace('workflow.replay', {}, async (replaySpan) => {
304
- replaySpan?.setAttributes({
305
- ...Attribute.WorkflowEventsCount(events.length),
306
- });
307
- return await runWorkflow(workflowCode, workflowRun, events, encryptionKey);
390
+ workflowStartedAt = +workflowRun.startedAt;
391
+ span?.setAttributes({
392
+ ...Attribute.WorkflowRunStatus(workflowRun.status),
393
+ ...Attribute.WorkflowStartedAt(workflowStartedAt),
308
394
  });
309
- }
310
- catch (err) {
311
- // WorkflowSuspension is normal control flow — not an error
312
- if (WorkflowSuspension.is(err)) {
313
- const suspensionMessage = buildWorkflowSuspensionMessage(runId, err.stepCount, err.hookCount, err.waitCount);
314
- if (suspensionMessage) {
315
- runtimeLogger.debug(suspensionMessage);
316
- }
317
- const result = await handleSuspension({
318
- suspension: err,
319
- world,
320
- run: workflowRun,
321
- span,
322
- requestId,
395
+ if (workflowRun.status !== 'running') {
396
+ // Workflow has already completed or failed, so we can skip it
397
+ runtimeLogger.info('Workflow already completed or failed, skipping', {
398
+ workflowRunId: runId,
399
+ status: workflowRun.status,
323
400
  });
324
- if (result.timeoutSeconds !== undefined) {
325
- return { timeoutSeconds: result.timeoutSeconds };
326
- }
327
- // Suspension handled, no further work needed
401
+ // TODO: for `cancel`, we actually want to propagate a WorkflowCancelled event
402
+ // inside the workflow context so the user can gracefully exit. this is SIGTERM
403
+ // TODO: furthermore, there should be a timeout or a way to force cancel SIGKILL
404
+ // so that we actually exit here without replaying the workflow at all, in the case
405
+ // the replaying the workflow is itself failing.
328
406
  return;
329
407
  }
330
- // This is a user code error or a WorkflowRuntimeError
331
- // (e.g., corrupted event log). Fail the workflow run.
332
- // Record exception for OTEL error tracking
333
- if (err instanceof Error) {
334
- span?.recordException?.(err);
408
+ } // end if (!workflowRun)
409
+ // Resolve the encryption key for this run's deployment.
410
+ // Used eagerly here since both runWorkflow (input
411
+ // hydration / hook payload decryption) and the run_failed
412
+ // dehydrate path below need it. Memoized accessor: first
413
+ // call triggers the actual fetch / HKDF derivation,
414
+ // subsequent calls await the cached promise.
415
+ const getEncryptionKey = memoizeEncryptionKey(world, workflowRun);
416
+ const encryptionKey = await getEncryptionKey();
417
+ // Main replay loop
418
+ // biome-ignore lint/correctness/noConstantCondition: intentional loop
419
+ while (true) {
420
+ loopIteration++;
421
+ // Replay-budget check: bail out (retry or fail) if
422
+ // non-step time within this invocation has exceeded
423
+ // the configured budget. Step bodies are excluded
424
+ // because replayBudget.pause()/resume() bracket every
425
+ // `executeStep` call.
426
+ if (replayBudget.isExhausted()) {
427
+ await handleReplayBudgetExhausted({
428
+ runId,
429
+ workflowName,
430
+ requestId,
431
+ attempt: metadata.attempt,
432
+ limitMs: replayBudget.configuredLimitMs,
433
+ });
434
+ // On Vercel, handleReplayBudgetExhausted always
435
+ // exits the process. On local dev it returns; we
436
+ // fall through and the request ends normally
437
+ // (run_failed has been written best-effort).
438
+ return;
335
439
  }
336
- const normalizedError = await normalizeUnknownError(err);
337
- const errorName = normalizedError.name || getErrorName(err);
338
- const errorMessage = normalizedError.message;
339
- let errorStack = normalizedError.stack || getErrorStack(err);
340
- // Remap error stack using source maps to show original source locations
341
- if (errorStack) {
342
- const parsedName = parseWorkflowName(workflowName);
343
- const filename = parsedName?.moduleSpecifier || workflowName;
344
- errorStack = remapErrorStack(errorStack, filename, workflowCode);
440
+ // Check timeout before replay
441
+ if (Date.now() - invocationStartTime >=
442
+ NO_INLINE_REPLAY_AFTER_MS) {
443
+ runtimeLogger.info('V2 timeout reached, re-scheduling workflow', {
444
+ workflowRunId: runId,
445
+ loopIteration,
446
+ elapsedMs: Date.now() - invocationStartTime,
447
+ });
448
+ await queueMessage(world, getWorkflowQueueName(workflowName), {
449
+ runId,
450
+ traceCarrier: await serializeTraceCarrier(),
451
+ requestedAt: new Date(),
452
+ });
453
+ return;
345
454
  }
346
- // Classify the error: WorkflowRuntimeError indicates an
347
- // internal issue (corrupted event log, missing data);
348
- // everything else is a user code error.
349
- const errorCode = classifyRunError(err);
350
- runtimeLogger.error('Error while running workflow', {
351
- workflowRunId: runId,
352
- errorCode,
353
- errorName,
354
- errorStack,
355
- });
356
- // Fail the workflow run via event (event-sourced architecture)
455
+ let replayStart = 0;
357
456
  try {
358
- await world.events.create(runId, {
359
- eventType: 'run_failed',
457
+ // Load events — use cached events with incremental fetch on subsequent iterations.
458
+ // The server always returns a cursor when there are events (even on the
459
+ // final page), so we can reliably use it for incremental loading.
460
+ let events;
461
+ if (cachedEvents === null) {
462
+ // First iteration: use preloaded events if available,
463
+ // otherwise do a full load with cursor.
464
+ if (preloadedEvents) {
465
+ events = preloadedEvents;
466
+ eventsCursor = preloadedEventsCursor ?? null;
467
+ }
468
+ else {
469
+ const loaded = await loadWorkflowRunEvents(runId);
470
+ events = loaded.events;
471
+ eventsCursor = loaded.cursor;
472
+ }
473
+ }
474
+ else if (eventsCursor) {
475
+ // Subsequent iteration: fetch only new events since last cursor
476
+ const loaded = await loadWorkflowRunEvents(runId, eventsCursor);
477
+ // Dedupe by eventId: a previous iteration may have
478
+ // appended a refreshed wait-completion delta before
479
+ // the next loop observes the advanced cursor, so an
480
+ // incremental fetch can return events we already have
481
+ // locally.
482
+ if (loaded.events.length > 0) {
483
+ const existingIds = new Set(cachedEvents.map((e) => e.eventId));
484
+ for (const e of loaded.events) {
485
+ if (!existingIds.has(e.eventId)) {
486
+ existingIds.add(e.eventId);
487
+ cachedEvents.push(e);
488
+ }
489
+ }
490
+ }
491
+ eventsCursor = loaded.cursor ?? eventsCursor;
492
+ events = cachedEvents;
493
+ }
494
+ else if (preloadedEvents) {
495
+ // Iteration 2 after iteration 1 used preloaded events
496
+ // (which don't carry a cursor). Do a full load now to
497
+ // pick up any events written since the preloaded set
498
+ // and obtain a cursor for subsequent incremental
499
+ // loads. This is the expected path, not a bug.
500
+ runtimeLogger.debug('No cursor after preloaded-events first iteration; doing full reload to pick up cursor.', { workflowRunId: runId });
501
+ const loaded = await loadWorkflowRunEvents(runId);
502
+ cachedEvents = loaded.events;
503
+ eventsCursor = loaded.cursor;
504
+ events = cachedEvents;
505
+ }
506
+ else {
507
+ // No cursor available despite having cached events
508
+ // and no preloaded-events explanation. All World
509
+ // implementations are required to return a cursor
510
+ // when there are events, so this signals a bug in
511
+ // the World. Fall back to a full reload to avoid
512
+ // stale data.
513
+ runtimeLogger.warn('Event cursor missing after initial load — falling back to full reload. ' +
514
+ 'This indicates a bug in the World implementation.', { workflowRunId: runId });
515
+ const loaded = await loadWorkflowRunEvents(runId);
516
+ cachedEvents = loaded.events;
517
+ eventsCursor = loaded.cursor;
518
+ events = cachedEvents;
519
+ }
520
+ // Detect concurrent completion via the event log: if
521
+ // any other handler wrote a terminal run event, exit
522
+ // before doing replay work. The run entity's status is
523
+ // derived from these events, so checking the log here
524
+ // gives us the same signal as a runs.get() round-trip
525
+ // without the extra request per loop iteration.
526
+ // Terminal run events are always last by construction
527
+ // (no event creation succeeds against a terminal run),
528
+ // but scan the full array for defense-in-depth: a
529
+ // World/backend ordering bug shouldn't make us miss
530
+ // an actual termination signal.
531
+ const terminalRunEvent = events.find((e) => e.eventType === 'run_completed' ||
532
+ e.eventType === 'run_failed' ||
533
+ e.eventType === 'run_cancelled');
534
+ if (terminalRunEvent) {
535
+ runtimeLogger.debug('Run completed by concurrent handler, exiting', {
536
+ workflowRunId: runId,
537
+ eventType: terminalRunEvent.eventType,
538
+ });
539
+ return;
540
+ }
541
+ // Complete elapsed waits
542
+ const now = Date.now();
543
+ const completedWaitIds = new Set(events
544
+ .filter((e) => e.eventType === 'wait_completed')
545
+ .map((e) => e.correlationId));
546
+ const waitsToComplete = events
547
+ .filter((e) => e.eventType === 'wait_created' &&
548
+ e.correlationId !== undefined &&
549
+ !completedWaitIds.has(e.correlationId) &&
550
+ now >= e.eventData.resumeAt.getTime())
551
+ .map((e) => ({
552
+ eventType: 'wait_completed',
360
553
  specVersion: SPEC_VERSION_CURRENT,
554
+ correlationId: e.correlationId,
361
555
  eventData: {
362
- error: {
363
- message: errorMessage,
364
- stack: errorStack,
365
- },
366
- errorCode,
556
+ resumeAt: e.eventData.resumeAt,
367
557
  },
368
- }, { requestId });
558
+ }));
559
+ for (const waitEvent of waitsToComplete) {
560
+ try {
561
+ await world.events.create(runId, waitEvent, {
562
+ requestId,
563
+ });
564
+ }
565
+ catch (err) {
566
+ if (EntityConflictError.is(err)) {
567
+ runtimeLogger.info('Wait already completed, skipping', {
568
+ workflowRunId: runId,
569
+ correlationId: waitEvent.correlationId,
570
+ });
571
+ continue;
572
+ }
573
+ throw err;
574
+ }
575
+ }
576
+ if (waitsToComplete.length > 0) {
577
+ // The event list above may be stale by the time an
578
+ // elapsed wait is committed. Load only events after
579
+ // the original snapshot cursor so concurrent durable
580
+ // events, such as hook_received, keep their ordering
581
+ // relative to wait_completed. Fall back to a full
582
+ // reload for older worlds that cannot give us a stable
583
+ // cursor, or if the cursor delta does not include the
584
+ // wait completion this handler just attempted.
585
+ if (eventsCursor) {
586
+ const loaded = await loadWorkflowRunEvents(runId, eventsCursor);
587
+ const completedWaitIdsAfterCursor = new Set(loaded.events
588
+ .filter((e) => e.eventType === 'wait_completed')
589
+ .map((e) => e.correlationId));
590
+ const sawAllWaitCompletions = waitsToComplete.every((waitEvent) => completedWaitIdsAfterCursor.has(waitEvent.correlationId));
591
+ if (sawAllWaitCompletions) {
592
+ const existingIds = new Set(events.map((e) => e.eventId));
593
+ for (const event of loaded.events) {
594
+ if (!existingIds.has(event.eventId)) {
595
+ existingIds.add(event.eventId);
596
+ events.push(event);
597
+ }
598
+ }
599
+ eventsCursor = loaded.cursor ?? eventsCursor;
600
+ }
601
+ else {
602
+ const loaded = await loadWorkflowRunEvents(runId);
603
+ events = loaded.events;
604
+ eventsCursor = loaded.cursor;
605
+ }
606
+ }
607
+ else {
608
+ const loaded = await loadWorkflowRunEvents(runId);
609
+ events = loaded.events;
610
+ eventsCursor = loaded.cursor;
611
+ }
612
+ }
613
+ // Update cache reference (may have been set for first time)
614
+ cachedEvents = events;
615
+ // Replay workflow
616
+ runtimeLogger.debug('Starting workflow replay', {
617
+ workflowRunId: runId,
618
+ loopIteration,
619
+ eventCount: events.length,
620
+ });
621
+ replayStart = Date.now();
622
+ const result = await runWorkflow(workflowCode, workflowRun, events, encryptionKey);
623
+ runtimeLogger.debug('Workflow replay completed', {
624
+ workflowRunId: runId,
625
+ loopIteration,
626
+ replayMs: Date.now() - replayStart,
627
+ });
628
+ // Workflow completed
629
+ try {
630
+ await world.events.create(runId, {
631
+ eventType: 'run_completed',
632
+ specVersion: SPEC_VERSION_CURRENT,
633
+ eventData: { output: result },
634
+ }, { requestId });
635
+ }
636
+ catch (err) {
637
+ if (EntityConflictError.is(err) ||
638
+ RunExpiredError.is(err)) {
639
+ runtimeLogger.info('Tried completing workflow run, but run has already finished.', { workflowRunId: runId, message: err.message });
640
+ return;
641
+ }
642
+ throw err;
643
+ }
644
+ span?.setAttributes({
645
+ ...Attribute.WorkflowRunStatus('completed'),
646
+ });
647
+ return;
369
648
  }
370
- catch (failErr) {
371
- if (EntityConflictError.is(failErr) ||
372
- RunExpiredError.is(failErr)) {
373
- runtimeLogger.info('Tried failing workflow run, but run has already finished.', {
649
+ catch (err) {
650
+ if (WorkflowSuspension.is(err)) {
651
+ runtimeLogger.debug('Workflow suspended', {
374
652
  workflowRunId: runId,
375
- message: failErr.message,
653
+ loopIteration,
654
+ replayMs: Date.now() - replayStart,
655
+ steps: err.stepCount,
656
+ hooks: err.hookCount,
657
+ waits: err.waitCount,
376
658
  });
659
+ const suspensionMessage = buildWorkflowSuspensionMessage(err.stepCount, err.hookCount, err.waitCount);
660
+ if (suspensionMessage) {
661
+ runtimeLogger.debug(suspensionMessage);
662
+ }
663
+ // V2: handle suspension without queuing steps
664
+ const suspensionStart = Date.now();
665
+ const suspensionResult = await handleSuspension({
666
+ suspension: err,
667
+ world,
668
+ run: workflowRun,
669
+ span,
670
+ requestId,
671
+ });
672
+ runtimeLogger.debug('Suspension handled', {
673
+ workflowRunId: runId,
674
+ suspensionMs: Date.now() - suspensionStart,
675
+ pendingSteps: suspensionResult.pendingSteps.length,
676
+ timeoutSeconds: suspensionResult.timeoutSeconds,
677
+ hasHookConflict: suspensionResult.hasHookConflict,
678
+ });
679
+ // Hook conflict: break loop, re-invoke via queue
680
+ if (suspensionResult.hasHookConflict) {
681
+ return { timeoutSeconds: 0 };
682
+ }
683
+ const pendingSteps = suspensionResult.pendingSteps;
684
+ if (pendingSteps.length === 0) {
685
+ // No steps — only waits/hooks
686
+ if (suspensionResult.timeoutSeconds !== undefined) {
687
+ return {
688
+ timeoutSeconds: suspensionResult.timeoutSeconds,
689
+ };
690
+ }
691
+ return;
692
+ }
693
+ // Inline execution is gated on ownership: only the
694
+ // handler that actually wrote the step_created event
695
+ // may run the step body inline. The world-level
696
+ // step_created is atomic per-correlationId, so
697
+ // exactly one handler owns each step — concurrent
698
+ // handlers can't race on step execution.
699
+ const ownedPendingSteps = pendingSteps.filter((s) => suspensionResult.createdStepCorrelationIds.has(s.correlationId));
700
+ // Pick one owned step to execute inline (if any).
701
+ // The rest of the pending steps are queued below.
702
+ //
703
+ // Skip inline execution entirely when the suspension
704
+ // also has a pending wait (sleep): an inline `await
705
+ // executeStep(...)` blocks the handler for the full
706
+ // step duration, so the wait timer never has a chance
707
+ // to fire on time. That defeats `Promise.race(step,
708
+ // sleep)` semantics — if the sleep is shorter than
709
+ // the step, replay still picks the step because
710
+ // wait_completed is only created on the *next* loop
711
+ // iteration, which doesn't run until the step
712
+ // finishes. Queueing every step in this case lets
713
+ // the wait timeout drive a continuation in parallel,
714
+ // matching V1's behavior where each step ran in a
715
+ // separate function invocation.
716
+ const inlineStep = suspensionResult.timeoutSeconds === undefined
717
+ ? ownedPendingSteps[0]
718
+ : undefined;
719
+ // Queue every pending step except the one we're
720
+ // executing inline. This mirrors V1's unconditional
721
+ // enqueue-with-idempotency pattern and is what makes
722
+ // crash recovery work: if a prior handler wrote
723
+ // step_created events but crashed before enqueuing,
724
+ // a later handler (e.g., from flow-message
725
+ // redelivery or reenqueueActiveRuns) will enqueue
726
+ // the orphaned steps. In the happy path with a
727
+ // single owner, concurrent handlers' queue attempts
728
+ // dedupe on correlationId. Skipping the inline step
729
+ // avoids a queue handler racing against our own
730
+ // inline executor.
731
+ for (const step of pendingSteps) {
732
+ if (inlineStep &&
733
+ step.correlationId === inlineStep.correlationId) {
734
+ continue;
735
+ }
736
+ const traceCarrier = await serializeTraceCarrier();
737
+ await queueMessage(world, getWorkflowQueueName(workflowName), {
738
+ runId,
739
+ stepId: step.correlationId,
740
+ stepName: step.stepName,
741
+ traceCarrier,
742
+ requestedAt: new Date(),
743
+ }, {
744
+ idempotencyKey: step.correlationId,
745
+ });
746
+ }
747
+ // Nothing to execute inline — we already queued all
748
+ // pending steps above, exit and let the queue drive.
749
+ if (!inlineStep) {
750
+ if (suspensionResult.timeoutSeconds !== undefined) {
751
+ return {
752
+ timeoutSeconds: suspensionResult.timeoutSeconds,
753
+ };
754
+ }
755
+ return;
756
+ }
757
+ // Execute inline step. Pause the replay budget
758
+ // for the duration of the step body — step
759
+ // duration is bounded by the platform's function
760
+ // maxDuration, not by the replay timeout. Without
761
+ // this the replay-budget check at the top of the
762
+ // next loop iteration would (incorrectly) charge
763
+ // the step body against the budget.
764
+ replayBudget.pause();
765
+ let stepResult;
766
+ try {
767
+ stepResult = await executeStep({
768
+ world,
769
+ workflowRunId: runId,
770
+ workflowDeploymentId: workflowRun.deploymentId,
771
+ workflowName,
772
+ workflowStartedAt,
773
+ stepId: inlineStep.correlationId,
774
+ stepName: inlineStep.stepName,
775
+ });
776
+ }
777
+ finally {
778
+ replayBudget.resume();
779
+ }
780
+ if (stepResult.type === 'retry') {
781
+ // Step needs retry — queue self with stepId for retry
782
+ const traceCarrier = await serializeTraceCarrier();
783
+ await queueMessage(world, getWorkflowQueueName(workflowName), {
784
+ runId,
785
+ stepId: inlineStep.correlationId,
786
+ stepName: inlineStep.stepName,
787
+ traceCarrier,
788
+ requestedAt: new Date(),
789
+ }, {
790
+ delaySeconds: stepResult.timeoutSeconds,
791
+ });
792
+ // If there are also waits, return their timeout
793
+ if (suspensionResult.timeoutSeconds !== undefined) {
794
+ return {
795
+ timeoutSeconds: suspensionResult.timeoutSeconds,
796
+ };
797
+ }
798
+ return;
799
+ }
800
+ if (stepResult.type === 'throttled') {
801
+ return {
802
+ timeoutSeconds: stepResult.timeoutSeconds,
803
+ };
804
+ }
805
+ // Step completed or failed — loop back to replay
806
+ // (gone/skipped also loop back since the workflow
807
+ // will see the completed/failed event on replay)
808
+ // If the step had pending background ops (e.g., stream
809
+ // writes to S3), break the loop and return so waitUntil
810
+ // can flush them. This matches V1 behavior where each
811
+ // step ran in a separate function invocation. Without
812
+ // this, the inline loop continues and the stream data
813
+ // may not reach S3 before the test tries to read it.
814
+ if (stepResult.type === 'completed' &&
815
+ stepResult.hasPendingOps) {
816
+ runtimeLogger.debug('Breaking loop: step has pending ops', {
817
+ workflowRunId: runId,
818
+ loopIteration,
819
+ stepName: inlineStep.stepName,
820
+ });
821
+ await queueMessage(world, getWorkflowQueueName(workflowName), {
822
+ runId,
823
+ traceCarrier: await serializeTraceCarrier(),
824
+ requestedAt: new Date(),
825
+ });
826
+ return;
827
+ }
828
+ if (suspensionResult.timeoutSeconds !== undefined &&
829
+ pendingSteps.length === 1) {
830
+ // Only 1 step and there's also waits/hooks,
831
+ // step is done, but we need the wait timeout
832
+ // Loop back to replay which will re-evaluate
833
+ }
834
+ }
835
+ else {
836
+ // User code error from runWorkflow — create run_failed.
837
+ if (err instanceof Error) {
838
+ span?.recordException?.(err);
839
+ }
840
+ const normalizedError = await normalizeUnknownError(err);
841
+ const errorName = normalizedError.name || getErrorName(err);
842
+ const errorMessage = normalizedError.message;
843
+ let errorStack = normalizedError.stack || getErrorStack(err);
844
+ if (errorStack) {
845
+ const parsedName = parseWorkflowName(workflowName);
846
+ const filename = parsedName?.moduleSpecifier || workflowName;
847
+ errorStack = remapErrorStack(errorStack, filename, workflowCode);
848
+ }
849
+ // Classify the error: WorkflowRuntimeError indicates
850
+ // an SDK/runtime issue, and selected subclasses use
851
+ // more specific codes for backend tracking.
852
+ const errorCode = classifyRunError(err);
853
+ runtimeLogger.error('Error while running workflow', {
854
+ workflowRunId: runId,
855
+ errorCode,
856
+ errorName,
857
+ errorStack,
858
+ });
859
+ // Apply the source-map-remapped stack to the thrown
860
+ // value so that the serialized error preserves it
861
+ // for consumers. `types.isNativeError()` is used
862
+ // instead of `err instanceof Error` because the
863
+ // workflow runs in a separate VM realm — its Error
864
+ // class is distinct from the host's, so `instanceof
865
+ // Error` is `false` for VM-thrown errors. The V8
866
+ // type tag works across realms.
867
+ if (types.isNativeError(err) && errorStack) {
868
+ err.stack = errorStack;
869
+ }
870
+ // Fail the workflow run via event (event-sourced).
871
+ // Serialize the original thrown value so its full
872
+ // type identity and custom properties round-trip
873
+ // through the event log.
874
+ try {
875
+ await world.events.create(runId, {
876
+ eventType: 'run_failed',
877
+ specVersion: SPEC_VERSION_CURRENT,
878
+ eventData: {
879
+ error: await dehydrateRunError(err, runId, encryptionKey),
880
+ errorCode,
881
+ },
882
+ }, { requestId });
883
+ }
884
+ catch (failErr) {
885
+ if (EntityConflictError.is(failErr) ||
886
+ RunExpiredError.is(failErr)) {
887
+ runtimeLogger.info('Tried failing workflow run, but run has already finished.', {
888
+ workflowRunId: runId,
889
+ message: failErr.message,
890
+ });
891
+ return;
892
+ }
893
+ if (isWorldContractError(failErr)) {
894
+ runtimeLogger.error('Fatal world contract error while recording workflow failure', {
895
+ workflowRunId: runId,
896
+ errorCode: RUN_ERROR_CODES.WORLD_CONTRACT_ERROR,
897
+ error: failErr instanceof Error
898
+ ? failErr.message
899
+ : String(failErr),
900
+ });
901
+ return;
902
+ }
903
+ throw failErr;
904
+ }
377
905
  span?.setAttributes({
906
+ ...Attribute.WorkflowRunStatus('failed'),
378
907
  ...Attribute.WorkflowErrorCode(errorCode),
379
908
  ...Attribute.WorkflowErrorName(errorName),
380
909
  ...Attribute.WorkflowErrorMessage(errorMessage),
@@ -382,54 +911,10 @@ export function workflowEntrypoint(workflowCode) {
382
911
  });
383
912
  return;
384
913
  }
385
- else {
386
- throw failErr;
387
- }
388
- }
389
- span?.setAttributes({
390
- ...Attribute.WorkflowRunStatus('failed'),
391
- ...Attribute.WorkflowErrorCode(errorCode),
392
- ...Attribute.WorkflowErrorName(errorName),
393
- ...Attribute.WorkflowErrorMessage(errorMessage),
394
- ...Attribute.ErrorType(errorName),
395
- });
396
- return;
397
- }
398
- // --- Infrastructure: complete the run ---
399
- // This is outside the user-code try/catch so that failures
400
- // here (e.g., network errors) propagate to the queue handler.
401
- try {
402
- await world.events.create(runId, {
403
- eventType: 'run_completed',
404
- specVersion: SPEC_VERSION_CURRENT,
405
- eventData: {
406
- output: workflowResult,
407
- },
408
- }, { requestId });
409
- }
410
- catch (err) {
411
- if (EntityConflictError.is(err) ||
412
- RunExpiredError.is(err)) {
413
- runtimeLogger.info('Tried completing workflow run, but run has already finished.', {
414
- workflowRunId: runId,
415
- message: err.message,
416
- });
417
- return;
418
914
  }
419
- else {
420
- throw err;
421
- }
422
- }
423
- span?.setAttributes({
424
- ...Attribute.WorkflowRunStatus('completed'),
425
- ...Attribute.WorkflowEventsCount(events.length),
426
- });
915
+ } // End while loop
427
916
  }); // End trace
428
917
  }); // End withWorkflowBaggage
429
- }).finally(() => {
430
- if (replayTimeout) {
431
- clearTimeout(replayTimeout);
432
- }
433
918
  }); // End withTraceContext
434
919
  });
435
920
  let cachedHandler;
@@ -440,7 +925,4 @@ export function workflowEntrypoint(workflowCode) {
440
925
  return cachedHandler(req);
441
926
  });
442
927
  }
443
- // this is a no-op placeholder as the client is
444
- // expecting this to be present but we aren't actually using it
445
- export function runStep() { }
446
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVudGltZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9ydW50aW1lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxtQkFBbUIsRUFDbkIsZUFBZSxFQUNmLGVBQWUsRUFDZixvQkFBb0IsR0FDckIsTUFBTSxrQkFBa0IsQ0FBQztBQUMxQixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUMvRCxPQUFPLEVBRUwsb0JBQW9CLEVBQ3BCLDJCQUEyQixHQUU1QixNQUFNLGlCQUFpQixDQUFDO0FBQ3pCLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUM1QyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDakQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUM1QyxPQUFPLEVBQ0wsb0JBQW9CLEVBQ3BCLGlCQUFpQixHQUNsQixNQUFNLHdCQUF3QixDQUFDO0FBQ2hDLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsZ0JBQWdCLEVBQ2hCLHdCQUF3QixFQUN4Qix1QkFBdUIsRUFDdkIsZUFBZSxHQUNoQixNQUFNLHNCQUFzQixDQUFDO0FBQzlCLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ25FLE9BQU8sRUFDTCxRQUFRLEVBQ1IsZ0JBQWdCLEdBRWpCLE1BQU0sb0JBQW9CLENBQUM7QUFDNUIsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ2xELE9BQU8sS0FBSyxTQUFTLE1BQU0scUNBQXFDLENBQUM7QUFDakUsT0FBTyxFQUNMLG9CQUFvQixFQUNwQixLQUFLLEVBQ0wsZ0JBQWdCLEVBQ2hCLG1CQUFtQixHQUNwQixNQUFNLGdCQUFnQixDQUFDO0FBQ3hCLE9BQU8sRUFBRSxZQUFZLEVB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
928
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVudGltZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9ydW50aW1lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDbEMsT0FBTyxFQUNMLG1CQUFtQixFQUNuQixVQUFVLEVBQ1YsZUFBZSxFQUVmLGVBQWUsRUFDZixvQkFBb0IsR0FDckIsTUFBTSxrQkFBa0IsQ0FBQztBQUMxQixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUMvRCxPQUFPLEVBRUwsb0JBQW9CLEVBQ3BCLDJCQUEyQixHQUc1QixNQUFNLGlCQUFpQixDQUFDO0FBQ3pCLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxvQkFBb0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzdFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDakQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUM1QyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM5RCxPQUFPLEVBQ0wsZ0JBQWdCLEVBQ2hCLG9CQUFvQixFQUNwQix3QkFBd0IsRUFDeEIscUJBQXFCLEVBQ3JCLG9CQUFvQixFQUNwQix1QkFBdUIsRUFDdkIsWUFBWSxFQUNaLGVBQWUsR0FDaEIsTUFBTSxzQkFBc0IsQ0FBQztBQUM5QixPQUFPLEVBQ0wsMkJBQTJCLEVBQzNCLFlBQVksR0FDYixNQUFNLDRCQUE0QixDQUFDO0FBQ3BDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNuRSxPQUFPLEVBQ0wsUUFBUSxFQUNSLGdCQUFnQixHQUVqQixNQUFNLG9CQUFvQixDQUFDO0FB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LFlBQVk7WUFDakIsQ0FBQyxDQUNGLENBQUMsQ0FBQywwQkFBMEI7UUFDL0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyx1QkFBdUI7SUFDN0IsQ0FBQyxDQUNGLENBQUM7SUFFSixJQUFJLGFBQWdFLENBQUM7SUFDckUsT0FBTyxlQUFlLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxFQUFFO1FBQ25DLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUNuQixhQUFhLEdBQUcsT0FBTyxDQUFDLE1BQU0sZ0JBQWdCLEVBQUUsQ0FBQyxDQUFDO1FBQ3BELENBQUM7UUFDRCxPQUFPLGFBQWEsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUM1QixDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyB0eXBlcyB9IGZyb20gJ25vZGU6dXRpbCc7XG5pbXBvcnQge1xuICBFbnRpdHlDb25mbGljdEVycm9yLFxuICBGYXRhbEVycm9yLFxuICBSVU5fRVJST1JfQ09ERVMsXG4gIHR5cGUgUnVuRXJyb3JDb2RlLFxuICBSdW5FeHBpcmVkRXJyb3IsXG4gIFdvcmtmbG93UnVudGltZUVycm9yLFxufSBmcm9tICdAd29ya2Zsb3cvZXJyb3JzJztcbmltcG9ydCB7IHBhcnNlV29ya2Zsb3dOYW1lIH0gZnJvbSAnQHdvcmtmbG93L3V0aWxzL3BhcnNlLW5hbWUnO1xuaW1wb3J0IHtcbiAgdHlwZSBFdmVudCxcbiAgU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gIFdvcmtmbG93SW52b2tlUGF5bG9hZFNjaGVtYSxcbiAgdHlwZSBXb3JrZmxvd1J1bixcbiAgdHlwZSBXb3JsZCxcbn0gZnJvbSAnQHdvcmtmbG93L3dvcmxkJztcbmltcG9ydCB7IGNsYXNzaWZ5UnVuRXJyb3IsIGlzV29ybGRDb250cmFjdEVycm9yIH0gZnJvbSAnLi9jbGFzc2lmeS1lcnJvci5qcyc7XG5pbXBvcnQgeyBkZXNjcmliZUVycm9yIH0gZnJvbSAnLi9kZXNjcmliZS1lcnJvci5qcyc7XG5pbXBvcnQgeyBXb3JrZmxvd1N1c3BlbnNpb24gfSBmcm9tICcuL2dsb2JhbC5qcyc7XG5pbXBvcnQgeyBydW50aW1lTG9nZ2VyIH0gZnJvbSAnLi9sb2dnZXIuanMnO1xuaW1wb3J0IHsgTUFYX1FVRVVFX0RFTElWRVJJRVMgfSBmcm9tICcuL3J1bnRpbWUvY29uc3RhbnRzLmpzJztcbmltcG9ydCB7XG4gIGdldFF1ZXVlT3ZlcmhlYWQsXG4gIGdldFdvcmtmbG93UXVldWVOYW1lLFxuICBoYW5kbGVIZWFsdGhDaGVja01lc3NhZ2UsXG4gIGxvYWRXb3JrZmxvd1J1bkV2ZW50cyxcbiAgbWVtb2l6ZUVuY3J5cHRpb25LZXksXG4gIHBhcnNlSGVhbHRoQ2hlY2tQYXlsb2FkLFxuICBxdWV1ZU1lc3NhZ2UsXG4gIHdpdGhIZWFsdGhDaGVjayxcbn0gZnJvbSAnLi9ydW50aW1lL2hlbHBlcnMuanMnO1xuaW1wb3J0IHtcbiAgaGFuZGxlUmVwbGF5QnVkZ2V0RXhoYXVzdGVkLFxuICBSZXBsYXlCdWRnZXQsXG59IGZyb20gJy4vcnVudGltZS9yZXBsYXktYnVkZ2V0LmpzJztcbmltcG9ydCB7IGV4ZWN1dGVTdGVwIH0gZnJvbSAnLi9ydW50aW1lL3N0ZXAtZXhlY3V0b3IuanMnO1xuaW1wb3J0IHsgaGFuZGxlU3VzcGVuc2lvbiB9IGZyb20gJy4vcnVudGltZS9zdXNwZW5zaW9uLWhhbmRsZXIuanMnO1xuaW1wb3J0IHtcbiAgZ2V0V29ybGQsXG4gIGdldFdvcmxkSGFuZGxlcnMsXG4gIHR5cGUgV29ybGRIYW5kbGVycyxcbn0gZnJvbSAnLi9ydW50aW1lL3dvcmxkLmpzJztcbmltcG9ydCB7IGRlaHlkcmF0ZVJ1bkVycm9yIH0gZnJvbSAnLi9zZXJpYWxpemF0aW9uLmpzJztcbmltcG9ydCB7IHJlbWFwRXJyb3JTdGFjayB9IGZyb20gJy4vc291cmNlLW1hcC5qcyc7XG5pbXBvcnQgKiBhcyBBdHRyaWJ1dGUgZnJvbSAnLi90ZWxlbWV0cnkvc2VtYW50aWMtY29udmVudGlvbnMuanMnO1xuaW1wb3J0IHtcbiAgbGlua1RvQ3VycmVudENvbnRleHQsXG4gIHNlcmlhbGl6ZVRyYWNlQ2FycmllcixcbiAgdHJhY2UsXG4gIHdpdGhUcmFjZUNvbnRleHQsXG4gIHdpdGhXb3JrZmxvd0JhZ2dhZ2UsXG59IGZyb20gJy4vdGVsZW1ldHJ5LmpzJztcbmltcG9ydCB7IGdldEVycm9yTmFtZSwgZ2V0RXJyb3JTdGFjaywgbm9ybWFsaXplVW5rbm93bkVycm9yIH0gZnJvbSAnLi90eXBlcy5qcyc7XG5pbXBvcnQgeyBidWlsZFdvcmtmbG93U3VzcGVuc2lvbk1lc3NhZ2UgfSBmcm9tICcuL3V0aWwuanMnO1xuaW1wb3J0IHsgcnVuV29ya2Zsb3cgfSBmcm9tICcuL3dvcmtmbG93LmpzJztcblxuZXhwb3J0IHR5cGUgeyBFdmVudCwgV29ya2Zsb3dSdW4gfTtcbmV4cG9ydCB7IFdvcmtmbG93U3VzcGVuc2lvbiB9IGZyb20gJy4vZ2xvYmFsLmpzJztcbmV4cG9ydCB7XG4gIHR5cGUgSGVhbHRoQ2hlY2tFbmRwb2ludCxcbiAgdHlwZSBIZWFsdGhDaGVja09wdGlvbnMsXG4gIHR5cGUgSGVhbHRoQ2hlY2tSZXN1bHQsXG4gIGhlYWx0aENoZWNrLFxufSBmcm9tICcuL3J1bnRpbWUvaGVscGVycy5qcyc7XG5leHBvcnQge1xuICBnZXRIb29rQnlUb2tlbixcbiAgcmVzdW1lSG9vayxcbiAgcmVzdW1lV2ViaG9vayxcbn0gZnJvbSAnLi9ydW50aW1lL3Jlc3VtZS1ob29rLmpzJztcbmV4cG9ydCB7XG4gIGdldFJ1bixcbiAgUnVuLFxuICB0eXBlIFdvcmtmbG93UmVhZGFibGVTdHJlYW0sXG4gIHR5cGUgV29ya2Zsb3dSZWFkYWJsZVN0cmVhbU9wdGlvbnMsXG59IGZyb20gJy4vcnVudGltZS9ydW4uanMnO1xuZXhwb3J0IHtcbiAgY2FuY2VsUnVuLFxuICBsaXN0U3RyZWFtcyxcbiAgdHlwZSBSZWFkU3RyZWFtT3B0aW9ucyxcbiAgdHlwZSBSZWNyZWF0ZVJ1bk9wdGlvbnMsXG4gIHJlYWRTdHJlYW0sXG4gIHJlY3JlYXRlUnVuRnJvbUV4aXN0aW5nLFxuICByZWVucXVldWVSdW4sXG4gIHR5cGUgU3RvcFNsZWVwT3B0aW9ucyxcbiAgdHlwZSBTdG9wU2xlZXBSZXN1bHQsXG4gIHdha2VVcFJ1bixcbn0gZnJvbSAnLi9ydW50aW1lL3J1bnMuanMnO1xuZXhwb3J0IHtcbiAgdHlwZSBTdGFydE9wdGlvbnMsXG4gIHR5cGUgU3RhcnRPcHRpb25zQmFzZSxcbiAgdHlwZSBTdGFydE9wdGlvbnNXaXRoRGVwbG95bWVudElkLFxuICB0eXBlIFN0YXJ0T3B0aW9uc1dpdGhvdXREZXBsb3ltZW50SWQsXG4gIHN0YXJ0LFxufSBmcm9tICcuL3J1bnRpbWUvc3RhcnQuanMnO1xuLy8gVjI6IHN0ZXBFbnRyeXBvaW50IGlzIG5vIGxvbmdlciByZS1leHBvcnRlZCDigJQgdGhlIGNvbWJpbmVkIGhhbmRsZXJcbi8vICh3b3JrZmxvd0VudHJ5cG9pbnQpIGV4ZWN1dGVzIHN0ZXBzIGlubGluZS4gUmVtb3ZpbmcgdGhlIHJlLWV4cG9ydFxuLy8gcHJldmVudHMgVHVyYm9wYWNrIGZyb20gdHJhY2luZyBzdGVwLWhhbmRsZXIuanMg4oaSIGdldC1wb3J0LmpzXG4vLyBmaWxlc3lzdGVtIG9wZXJhdGlvbnMgaW50byB0aGUgZmxvdyByb3V0ZSBidW5kbGUuXG5leHBvcnQge1xuICBjcmVhdGVXb3JsZCxcbiAgZ2V0V29ybGQsXG4gIGdldFdvcmxkSGFuZGxlcnMsXG4gIHNldFdvcmxkLFxufSBmcm9tICcuL3J1bnRpbWUvd29ybGQuanMnO1xuXG5mdW5jdGlvbiBnZXRXb3JrZmxvd1NldHVwRXJyb3JDb2RlKGVycjogdW5rbm93bik6IFJ1bkVycm9yQ29kZSB8IG51bGwge1xuICBpZiAoV29ya2Zsb3dSdW50aW1lRXJyb3IuaXMoZXJyKSkge1xuICAgIHJldHVybiBSVU5fRVJST1JfQ09ERVMuUlVOVElNRV9FUlJPUjtcbiAgfVxuXG4gIGlmIChpc1dvcmxkQ29udHJhY3RFcnJvcihlcnIpKSB7XG4gICAgcmV0dXJuIFJVTl9FUlJPUl9DT0RFUy5XT1JMRF9DT05UUkFDVF9FUlJPUjtcbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuXG5hc3luYyBmdW5jdGlvbiByZWNvcmRGYXRhbFJ1bkVycm9yKHtcbiAgd29ybGQsXG4gIHdvcmtmbG93UnVuLFxuICBydW5JZCxcbiAgcmVxdWVzdElkLFxuICBlcnIsXG4gIGVycm9yQ29kZSxcbiAgbG9nTWVzc2FnZSxcbn06IHtcbiAgd29ybGQ6IFdvcmxkO1xuICB3b3JrZmxvd1J1bjogV29ya2Zsb3dSdW4gfCB1bmRlZmluZWQ7XG4gIHJ1bklkOiBzdHJpbmc7XG4gIHJlcXVlc3RJZDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICBlcnI6IHVua25vd247XG4gIGVycm9yQ29kZTogUnVuRXJyb3JDb2RlO1xuICBsb2dNZXNzYWdlOiBzdHJpbmc7XG59KSB7XG4gIHJ1bnRpbWVMb2dnZXIuZXJyb3IobG9nTWVzc2FnZSwge1xuICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgIGVycm9yQ29kZSxcbiAgICBlcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpLFxuICB9KTtcblxuICB0cnkge1xuICAgIGNvbnN0IGdldEVuY3J5cHRpb25LZXkgPSBtZW1vaXplRW5jcnlwdGlvbktleSh3b3JsZCwgd29ya2Zsb3dSdW4gPz8gcnVuSWQpO1xuICAgIGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUoXG4gICAgICBydW5JZCxcbiAgICAgIHtcbiAgICAgICAgZXZlbnRUeXBlOiAncnVuX2ZhaWxlZCcsXG4gICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgZXJyb3I6IGF3YWl0IGRlaHlkcmF0ZVJ1bkVycm9yKGVyciwgcnVuSWQsIGF3YWl0IGdldEVuY3J5cHRpb25LZXkoKSksXG4gICAgICAgICAgZXJyb3JDb2RlLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIHsgcmVxdWVzdElkIH1cbiAgICApO1xuICB9IGNhdGNoIChmYWlsRXJyKSB7XG4gICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZmFpbEVycikgfHwgUnVuRXhwaXJlZEVycm9yLmlzKGZhaWxFcnIpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChpc1dvcmxkQ29udHJhY3RFcnJvcihmYWlsRXJyKSkge1xuICAgICAgcnVudGltZUxvZ2dlci5lcnJvcihcbiAgICAgICAgJ0ZhdGFsIHdvcmxkIGNvbnRyYWN0IGVycm9yIHdoaWxlIHJlY29yZGluZyB3b3JrZmxvdyBmYWlsdXJlJyxcbiAgICAgICAge1xuICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgIGVycm9yQ29kZTogUlVOX0VSUk9SX0NPREVTLldPUkxEX0NPTlRSQUNUX0VSUk9SLFxuICAgICAgICAgIGVycm9yOiBmYWlsRXJyIGluc3RhbmNlb2YgRXJyb3IgPyBmYWlsRXJyLm1lc3NhZ2UgOiBTdHJpbmcoZmFpbEVyciksXG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRocm93IGZhaWxFcnI7XG4gIH1cbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgc2luZ2xlIHJvdXRlIHdoaWNoIGhhbmRsZXMgd29ya2Zsb3cgZXhlY3V0aW9uIHJlcXVlc3RzLFxuICogZXhlY3V0aW5nIHN0ZXBzIGlubGluZSB3aGVuIHBvc3NpYmxlIHRvIHJlZHVjZSBmdW5jdGlvbiBpbnZvY2F0aW9uc1xuICogYW5kIHF1ZXVlIG92ZXJoZWFkLlxuICpcbiAqIFRoZSBoYW5kbGVyIGxvb3BzOiByZXBsYXkgd29ya2Zsb3cg4oaSIGV4ZWN1dGUgc3RlcCBpbmxpbmUg4oaSIHJlcGxheSDihpIgLi4uXG4gKiB1bnRpbCB0aGUgd29ya2Zsb3cgY29tcGxldGVzLCB0aW1lcyBvdXQsIG9yIGVuY291bnRlcnMgbm9uLXN0ZXAgc3VzcGVuc2lvbnMuXG4gKlxuICogQHBhcmFtIHdvcmtmbG93Q29kZSAtIFRoZSB3b3JrZmxvdyBidW5kbGUgY29kZSBjb250YWluaW5nIGFsbCB3b3JrZmxvdyBmdW5jdGlvbnNcbiAqIEByZXR1cm5zIEEgZnVuY3Rpb24gdGhhdCBjYW4gYmUgdXNlZCBhcyBhIFZlcmNlbCBBUEkgcm91dGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdvcmtmbG93RW50cnlwb2ludChcbiAgd29ya2Zsb3dDb2RlOiBzdHJpbmdcbik6IChyZXE6IFJlcXVlc3QpID0+IFByb21pc2U8UmVzcG9uc2U+IHtcbiAgY29uc3QgTk9fSU5MSU5FX1JFUExBWV9BRlRFUl9NUyA9XG4gICAgTnVtYmVyKHByb2Nlc3MuZW52LldPUktGTE9XX1YyX1RJTUVPVVRfTVMpIHx8IDEyMF8wMDA7XG5cbiAgY29uc3QgaGFuZGxlciA9ICh3b3JsZEhhbmRsZXJzOiBXb3JsZEhhbmRsZXJzKSA9PlxuICAgIHdvcmxkSGFuZGxlcnMuY3JlYXRlUXVldWVIYW5kbGVyKFxuICAgICAgJ19fd2tmX3dvcmtmbG93XycsXG4gICAgICBhc3luYyAobWVzc2FnZV8sIG1ldGFkYXRhKSA9PiB7XG4gICAgICAgIC8vIENoZWNrIGlmIHRoaXMgaXMgYSBoZWFsdGggY2hlY2sgbWVzc2FnZVxuICAgICAgICAvLyBOT1RFOiBIZWFsdGggY2hlY2sgbWVzc2FnZXMgYXJlIGludGVudGlvbmFsbHkgdW5hdXRoZW50aWNhdGVkIGZvciBtb25pdG9yaW5nIHB1cnBvc2VzLlxuICAgICAgICAvLyBUaGV5IG9ubHkgd3JpdGUgYSBzaW1wbGUgc3RhdHVzIHJlc3BvbnNlIHRvIGEgc3RyZWFtIGFuZCBkbyBub3QgZXhwb3NlIHNlbnNpdGl2ZSBkYXRhLlxuICAgICAgICAvLyBUaGUgc3RyZWFtIG5hbWUgaW5jbHVkZXMgYSB1bmlxdWUgY29ycmVsYXRpb25JZCB0aGF0IG11c3QgYmUga25vd24gYnkgdGhlIGNhbGxlci5cbiAgICAgICAgY29uc3QgaGVhbHRoQ2hlY2sgPSBwYXJzZUhlYWx0aENoZWNrUGF5bG9hZChtZXNzYWdlXyk7XG4gICAgICAgIGlmIChoZWFsdGhDaGVjaykge1xuICAgICAgICAgIGF3YWl0IGhhbmRsZUhlYWx0aENoZWNrTWVzc2FnZShcbiAgICAgICAgICAgIGhlYWx0aENoZWNrLFxuICAgICAgICAgICAgJ3dvcmtmbG93JyxcbiAgICAgICAgICAgIHdvcmxkSGFuZGxlcnMuc3BlY1ZlcnNpb25cbiAgICAgICAgICApO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICBydW5JZCxcbiAgICAgICAgICB0cmFjZUNhcnJpZXI6IHRyYWNlQ29udGV4dCxcbiAgICAgICAgICByZXF1ZXN0ZWRBdCxcbiAgICAgICAgICBzdGVwSWQ6IGluY29taW5nU3RlcElkLFxuICAgICAgICAgIHN0ZXBOYW1lOiBpbmNvbWluZ1N0ZXBOYW1lLFxuICAgICAgICAgIHJ1bklucHV0LFxuICAgICAgICB9ID0gV29ya2Zsb3dJbnZva2VQYXlsb2FkU2NoZW1hLnBhcnNlKG1lc3NhZ2VfKTtcbiAgICAgICAgY29uc3QgeyByZXF1ZXN0SWQgfSA9IG1ldGFkYXRhO1xuICAgICAgICBjb25zdCB3b3JrZmxvd05hbWUgPSBtZXRhZGF0YS5xdWV1ZU5hbWUuc2xpY2UoJ19fd2tmX3dvcmtmbG93XycubGVuZ3RoKTtcblxuICAgICAgICAvLyAtLS0gTWF4IGRlbGl2ZXJ5IGNoZWNrIC0tLVxuICAgICAgICAvLyBFbmZvcmNlIG1heCBkZWxpdmVyeSBsaW1pdCBiZWZvcmUgYW55IGluZnJhc3RydWN0dXJlIGNhbGxzLlxuICAgICAgICAvLyBUaGlzIHByZXZlbnRzIHJ1bmF3YXkgd29ya2Zsb3dzIGZyb20gY29uc3VtaW5nIGluZmluaXRlIHF1ZXVlIGRlbGl2ZXJpZXMuXG4gICAgICAgIC8vIFNjb3BlZCBsb2dnZXIgZm9yIHRoaXMgcnVuIOKAlCBhdHRhY2hlcyBydW5JZC93b3JrZmxvd05hbWUgdG8gZXZlcnlcbiAgICAgICAgLy8gbG9nIGxpbmUgYW5kIGNoaWxkIGxvZ2dlcnMgYmVsb3csIHNvIGNhbGxlcnMgZG9uJ3QgcmVwZWF0IGl0LlxuICAgICAgICBjb25zdCBydW5Mb2dnZXIgPSBydW50aW1lTG9nZ2VyLmZvclJ1bihydW5JZCwgd29ya2Zsb3dOYW1lKTtcblxuICAgICAgICBpZiAobWV0YWRhdGEuYXR0ZW1wdCA+IE1BWF9RVUVVRV9ERUxJVkVSSUVTKSB7XG4gICAgICAgICAgY29uc3QgbWF4RGVsaXZlcmllc0Rlc2NyaXB0aW9uID0gZGVzY3JpYmVFcnJvcihcbiAgICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICAgIFJVTl9FUlJPUl9DT0RFUy5NQVhfREVMSVZFUklFU19FWENFRURFRFxuICAgICAgICAgICk7XG4gICAgICAgICAgcnVuTG9nZ2VyLmVycm9yKFxuICAgICAgICAgICAgYFdvcmtmbG93IGhhbmRsZXIgZXhjZWVkZWQgbWF4IGRlbGl2ZXJpZXMgKCR7bWV0YWRhdGEuYXR0ZW1wdH0vJHtNQVhfUVVFVUVfREVMSVZFUklFU30pYCxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgYXR0ZW1wdDogbWV0YWRhdGEuYXR0ZW1wdCxcbiAgICAgICAgICAgICAgZXJyb3JDb2RlOiBtYXhEZWxpdmVyaWVzRGVzY3JpcHRpb24uZXJyb3JDb2RlLFxuICAgICAgICAgICAgICBlcnJvckF0dHJpYnV0aW9uOiBtYXhEZWxpdmVyaWVzRGVzY3JpcHRpb24uYXR0cmlidXRpb24sXG4gICAgICAgICAgICB9XG4gICAgICAgICAgKTtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3Qgd29ybGQgPSBhd2FpdCBnZXRXb3JsZCgpO1xuICAgICAgICAgICAgY29uc3QgZ2V0RW5jcnlwdGlvbktleSA9IG1lbW9pemVFbmNyeXB0aW9uS2V5KHdvcmxkLCBydW5JZCk7XG4gICAgICAgICAgICBjb25zdCBlcnIgPSBuZXcgRmF0YWxFcnJvcihcbiAgICAgICAgICAgICAgYFdvcmtmbG93IGV4Y2VlZGVkIG1heGltdW0gcXVldWUgZGVsaXZlcmllcyAoJHttZXRhZGF0YS5hdHRlbXB0fS8ke01BWF9RVUVVRV9ERUxJVkVSSUVTfSlgXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgYXdhaXQgd29ybGQuZXZlbnRzLmNyZWF0ZShcbiAgICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBldmVudFR5cGU6ICdydW5fZmFpbGVkJyxcbiAgICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgICAgICBlcnJvcjogYXdhaXQgZGVoeWRyYXRlUnVuRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgIGVycixcbiAgICAgICAgICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGdldEVuY3J5cHRpb25LZXkoKVxuICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgIGVycm9yQ29kZTogUlVOX0VSUk9SX0NPREVTLk1BWF9ERUxJVkVSSUVTX0VYQ0VFREVELFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHsgcmVxdWVzdElkIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpIHx8IFJ1bkV4cGlyZWRFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgIC8vIFJ1biBhbHJlYWR5IGZpbmlzaGVkLCBjb25zdW1lIHRoZSBtZXNzYWdlIHNpbGVudGx5XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJ1bkxvZ2dlci5lcnJvcihcbiAgICAgICAgICAgICAgYEZhaWxlZCB0byBtYXJrIHJ1biBhcyBmYWlsZWQgYWZ0ZXIgJHttZXRhZGF0YS5hdHRlbXB0fSBkZWxpdmVyeSBhdHRlbXB0cy4gYCArXG4gICAgICAgICAgICAgICAgYEEgcGVyc2lzdGVudCBlcnJvciBpcyBwcmV2ZW50aW5nIHRoZSBydW4gZnJvbSBiZWluZyB0ZXJtaW5hdGVkLiBgICtcbiAgICAgICAgICAgICAgICBgVGhlIHJ1biB3aWxsIHJlbWFpbiBpbiBpdHMgY3VycmVudCBzdGF0ZSB1bnRpbCBtYW51YWxseSByZXNvbHZlZC4gYCArXG4gICAgICAgICAgICAgICAgYFRoaXMgaXMgbW9zdCBsaWtlbHkgZHVlIHRvIGEgcGVyc2lzdGVudCBvdXRhZ2Ugb2YgdGhlIHdvcmtmbG93IGJhY2tlbmQgYCArXG4gICAgICAgICAgICAgICAgYG9yIGEgYnVnIGluIHRoZSB3b3JrZmxvdyBydW50aW1lIGFuZCBzaG91bGQgYmUgcmVwb3J0ZWQgdG8gdGhlIFdvcmtmbG93IHRlYW0uYCxcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGF0dGVtcHQ6IG1ldGFkYXRhLmF0dGVtcHQsXG4gICAgICAgICAgICAgICAgZXJyb3JOYW1lOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5uYW1lIDogJ1Vua25vd25FcnJvcicsXG4gICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVyciksXG4gICAgICAgICAgICAgICAgZXJyb3JTdGFjazogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIuc3RhY2sgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHNwYW5MaW5rcyA9IGF3YWl0IGxpbmtUb0N1cnJlbnRDb250ZXh0KCk7XG5cbiAgICAgICAgLy8gLS0tIFJlcGxheSBidWRnZXQgYm9va2tlZXBpbmcgLS0tXG4gICAgICAgIC8vIFRoZSByZXBsYXkgYnVkZ2V0IGJvdW5kcyB0aGUgKm5vbi1zdGVwKiBwb3J0aW9uIG9mIGEgc2luZ2xlXG4gICAgICAgIC8vIGhhbmRsZXIgaW52b2NhdGlvbjogZGV0ZXJtaW5pc3RpYyBldmVudC1sb2cgcmVwbGF5LCB3b3JrZmxvdy1WTVxuICAgICAgICAvLyBleGVjdXRpb24gYmV0d2VlbiBzdGVwIGJvdW5kYXJpZXMsIHN1c3BlbnNpb24gaGFuZGxpbmcsIHF1ZXVlXG4gICAgICAgIC8vIHJvdW5kLXRyaXBzLCBldGMuIElubGluZSBzdGVwIGJvZGllcyAoYFwidXNlIHN0ZXBcImAgZnVuY3Rpb25zXG4gICAgICAgIC8vIGludm9rZWQgdmlhIGBleGVjdXRlU3RlcGApIGFyZSBpbnRlbnRpb25hbGx5IGV4Y2x1ZGVkIOKAlCB0aGV5IGFyZVxuICAgICAgICAvLyBib3VuZGVkIGJ5IHRoZSBwbGF0Zm9ybSdzIGZ1bmN0aW9uIGBtYXhEdXJhdGlvbmAgYW5kIHRoZVxuICAgICAgICAvLyBgTk9fSU5MSU5FX1JFUExBWV9BRlRFUl9NU2AgZWFybHktcmV0dXJuIGd1YXJkIGJlbG93LlxuICAgICAgICAvL1xuICAgICAgICAvLyBUaGUgYnVkZ2V0IGlzIGNoZWNrZWQgYXQgbG9vcCBib3VuZGFyaWVzICh0b3Agb2YgZWFjaCBgd2hpbGVgXG4gICAgICAgIC8vIGl0ZXJhdGlvbikuIE5vdGUgdGhpcyBpcyAqbGVzcyByZXNwb25zaXZlKiB0aGFuIHRoZSBvbGRcbiAgICAgICAgLy8gYHNldFRpbWVvdXRgLWJhc2VkIGFwcHJvYWNoOiBhIHNpbmdsZSBwYXRob2xvZ2ljYWwgYHJ1bldvcmtmbG93YFxuICAgICAgICAvLyBjYWxsIHByb2Nlc3NpbmcgYSBodWdlIGV2ZW50IGxvZyBjYW4gb3ZlcnNob290IHRoZSBidWRnZXQgYnkgdXBcbiAgICAgICAgLy8gdG8gb25lIGl0ZXJhdGlvbiBiZWZvcmUgYmFpbGluZy4gSW4gcHJhY3RpY2UgdGhlIGhlYWRyb29tIGJ1aWx0XG4gICAgICAgIC8vIGludG8gYE1BWF9SRVBMQVlfVElNRU9VVF9NU2AgKGFuZCB0aGUgcGxhdGZvcm0gYG1heER1cmF0aW9uYFxuICAgICAgICAvLyBTSUdURVJNIGFzIHVsdGltYXRlIGJhY2tzdG9wKSBnaXZlcyB1cyBzbGFjayDigJQgdGhlIHByZXZpb3VzXG4gICAgICAgIC8vIGBzZXRUaW1lb3V0YCBhcHByb2FjaCBhbHNvIHJlbGllZCBvbiB0aGUgcGxhdGZvcm0ga2lsbCBhcyB0aGVcbiAgICAgICAgLy8gaGFyZCBiYWNrc3RvcC4gRG8gKm5vdCogXCJmaXhcIiB0aGlzIGJ5IGFkZGluZyBhIGBzZXRJbnRlcnZhbGA7XG4gICAgICAgIC8vIGl0IHdvdWxkIHJpc2sgdGhlIHNhbWUgYnVnIHdlIGp1c3QgcmVtb3ZlZCAoYm91bmRpbmcgc3RlcFxuICAgICAgICAvLyBib2RpZXMpLlxuICAgICAgICAvL1xuICAgICAgICAvLyBFYXJsaWVyIHZlcnNpb25zIChwcmUtIzIwMDkgZml4KSB1c2VkIGEgc2luZ2xlIGBzZXRUaW1lb3V0YFxuICAgICAgICAvLyB0aGF0IGFsc28gYm91bmRlZCBzdGVwIGJvZGllcywgd2hpY2ggYnJva2UgYW55IHdvcmtmbG93IHdpdGggYVxuICAgICAgICAvLyBzaW5nbGUgc3RlcCBsb25nZXIgdGhhbiB0aGUgYnVkZ2V0LlxuICAgICAgICBjb25zdCByZXBsYXlCdWRnZXQgPSBuZXcgUmVwbGF5QnVkZ2V0KCk7XG5cbiAgICAgICAgcmV0dXJuIGF3YWl0IHdpdGhUcmFjZUNvbnRleHQodHJhY2VDb250ZXh0LCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIGF3YWl0IHdpdGhXb3JrZmxvd0JhZ2dhZ2UoXG4gICAgICAgICAgICB7IHdvcmtmbG93UnVuSWQ6IHJ1bklkLCB3b3JrZmxvd05hbWUgfSxcbiAgICAgICAgICAgIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgY29uc3Qgd29ybGQgPSBhd2FpdCBnZXRXb3JsZCgpO1xuICAgICAgICAgICAgICByZXR1cm4gdHJhY2UoXG4gICAgICAgICAgICAgICAgYFdPUktGTE9XX1YyICR7d29ya2Zsb3dOYW1lfWAsXG4gICAgICAgICAgICAgICAgeyBsaW5rczogc3BhbkxpbmtzIH0sXG4gICAgICAgICAgICAgICAgYXN5bmMgKHNwYW4pID0+IHtcbiAgICAgICAgICAgICAgICAgIHNwYW4/LnNldEF0dHJpYnV0ZXMoe1xuICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dOYW1lKHdvcmtmbG93TmFtZSksXG4gICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd09wZXJhdGlvbignZXhlY3V0ZV92MicpLFxuICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuTWVzc2FnaW5nU3lzdGVtKCd2ZXJjZWwtcXVldWUnKSxcbiAgICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLk1lc3NhZ2luZ0Rlc3RpbmF0aW9uTmFtZShtZXRhZGF0YS5xdWV1ZU5hbWUpLFxuICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuTWVzc2FnaW5nTWVzc2FnZUlkKG1ldGFkYXRhLm1lc3NhZ2VJZCksXG4gICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5NZXNzYWdpbmdPcGVyYXRpb25UeXBlKCdwcm9jZXNzJyksXG4gICAgICAgICAgICAgICAgICAgIC4uLmdldFF1ZXVlT3ZlcmhlYWQoeyByZXF1ZXN0ZWRBdCB9KSxcbiAgICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLldvcmtmbG93UnVuSWQocnVuSWQpLFxuICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dUcmFjZVByb3BhZ2F0ZWQoISF0cmFjZUNvbnRleHQpLFxuICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgIGNvbnN0IGludm9jYXRpb25TdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgICAgICAgbGV0IGxvb3BJdGVyYXRpb24gPSAwO1xuXG4gICAgICAgICAgICAgICAgICAvLyBFdmVudCBjYWNoZToga2VlcCBsb2FkZWQgZXZlbnRzIGluIG1lbW9yeSBhY3Jvc3MgbG9vcCBpdGVyYXRpb25zLlxuICAgICAgICAgICAgICAgICAgLy8gT24gdGhlIGZpcnN0IGl0ZXJhdGlvbiB3ZSBkbyBhIGZ1bGwgbG9hZDsgb24gc3Vic2VxdWVudCBpdGVyYXRpb25zXG4gICAgICAgICAgICAgICAgICAvLyB3ZSBmZXRjaCBvbmx5IGV2ZW50cyBjcmVhdGVkIGFmdGVyIHRoZSBsYXN0IGtub3duIGN1cnNvci5cbiAgICAgICAgICAgICAgICAgIGxldCBjYWNoZWRFdmVudHM6IEV2ZW50W10gfCBudWxsID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgIGxldCBldmVudHNDdXJzb3I6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuXG4gICAgICAgICAgICAgICAgICAvLyBTaGFyZWQgc3RhdGU6IHNldCBieSBlaXRoZXIgdGhlIGJhY2tncm91bmQgc3RlcCBwYXRoXG4gICAgICAgICAgICAgICAgICAvLyBvciB0aGUgcnVuX3N0YXJ0ZWQgc2V0dXAgYmVsb3cuXG4gICAgICAgICAgICAgICAgICBsZXQgd29ya2Zsb3dSdW46IFdvcmtmbG93UnVuIHwgdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgbGV0IHdvcmtmbG93U3RhcnRlZEF0ID0gLTE7XG4gICAgICAgICAgICAgICAgICBsZXQgcHJlbG9hZGVkRXZlbnRzOiBFdmVudFtdIHwgdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgbGV0IHByZWxvYWRlZEV2ZW50c0N1cnNvcjogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgICAgLy8gSWYgaW5jb21pbmcgbWVzc2FnZSBoYXMgYSBzdGVwSWQsIHRoaXMgaXMgYSBiYWNrZ3JvdW5kIHN0ZXBcbiAgICAgICAgICAgICAgICAgIC8vIGV4ZWN1dGlvbi4gRXhlY3V0ZSB0aGUgc3RlcCwgdGhlbiBjaGVjayBpZiBhbGwgcGFyYWxsZWwgc3RlcHNcbiAgICAgICAgICAgICAgICAgIC8vIGZyb20gdGhlIGJhdGNoIGFyZSBkb25lLiBJZiBzbywgcmVwbGF5IGlubGluZSAoc2F2aW5nIGEgcXVldWVcbiAgICAgICAgICAgICAgICAgIC8vIHJvdW5kdHJpcCkuIElmIG5vdCwgcmV0dXJuIOKAlCB0aGUgbGFzdCBoYW5kbGVyIHRvIGNvbXBsZXRlXG4gICAgICAgICAgICAgICAgICAvLyB3aWxsIHBpY2sgdXAgdGhlIHJlcGxheS5cbiAgICAgICAgICAgICAgICAgIGlmIChpbmNvbWluZ1N0ZXBJZCAmJiBpbmNvbWluZ1N0ZXBOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3QgYmdSdW4gPSBhd2FpdCB3b3JsZC5ydW5zLmdldChydW5JZCk7XG4gICAgICAgICAgICAgICAgICAgICAgaWYgKGJnUnVuLnN0YXR1cyAhPT0gJ3J1bm5pbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmRlYnVnKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAnUnVuIGFscmVhZHkgZmluaXNoZWQsIHNraXBwaW5nIGJhY2tncm91bmQgc3RlcCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHsgd29ya2Zsb3dSdW5JZDogcnVuSWQsIHN0YXR1czogYmdSdW4uc3RhdHVzIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGJnU3RhcnRlZEF0ID0gYmdSdW4uc3RhcnRlZEF0XG4gICAgICAgICAgICAgICAgICAgICAgICA/ICtiZ1J1bi5zdGFydGVkQXRcbiAgICAgICAgICAgICAgICAgICAgICAgIDogRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgICAvLyBQYXVzZSB0aGUgcmVwbGF5IGJ1ZGdldCB3aGlsZSB0aGUgc3RlcCBib2R5IHJ1bnMg4oCUXG4gICAgICAgICAgICAgICAgICAgICAgLy8gc3RlcCBkdXJhdGlvbiBpcyBib3VuZGVkIGJ5IHRoZSBwbGF0Zm9ybSdzIGZ1bmN0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgLy8gbWF4RHVyYXRpb24sIG5vdCBieSB0aGUgcmVwbGF5IHRpbWVvdXQuIFNlZSB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAvLyBSZXBsYXlCdWRnZXQgZG9jcyBmb3IgdGhlIGNvbnRyYWN0LlxuICAgICAgICAgICAgICAgICAgICAgIHJlcGxheUJ1ZGdldC5wYXVzZSgpO1xuICAgICAgICAgICAgICAgICAgICAgIGxldCBzdGVwUmVzdWx0OiBBd2FpdGVkPFJldHVyblR5cGU8dHlwZW9mIGV4ZWN1dGVTdGVwPj47XG4gICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXBSZXN1bHQgPSBhd2FpdCBleGVjdXRlU3RlcCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmxkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dEZXBsb3ltZW50SWQ6IGJnUnVuLmRlcGxveW1lbnRJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1N0YXJ0ZWRBdDogYmdTdGFydGVkQXQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXBJZDogaW5jb21pbmdTdGVwSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXBOYW1lOiBpbmNvbWluZ1N0ZXBOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlcGxheUJ1ZGdldC5yZXN1bWUoKTtcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgaWYgKHN0ZXBSZXN1bHQudHlwZSA9PT0gJ3JldHJ5Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsgdGltZW91dFNlY29uZHM6IHN0ZXBSZXN1bHQudGltZW91dFNlY29uZHMgfTtcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgaWYgKHN0ZXBSZXN1bHQudHlwZSA9PT0gJ3Rocm90dGxlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7IHRpbWVvdXRTZWNvbmRzOiBzdGVwUmVzdWx0LnRpbWVvdXRTZWNvbmRzIH07XG4gICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgLy8gSWYgc3RlcCBoYWQgcGVuZGluZyBvcHMgKHN0cmVhbSB3cml0ZXMpLCBicmVhayBhbmQgbGV0XG4gICAgICAgICAgICAgICAgICAgICAgLy8gd2FpdFVudGlsIGZsdXNoIHRoZW0g4oCUIGNhbid0IGNvbnRpbnVlIGlubGluZS5cbiAgICAgICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICBzdGVwUmVzdWx0LnR5cGUgPT09ICdjb21wbGV0ZWQnICYmXG4gICAgICAgICAgICAgICAgICAgICAgICBzdGVwUmVzdWx0Lmhhc1BlbmRpbmdPcHNcbiAgICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHF1ZXVlTWVzc2FnZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgd29ybGQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGdldFdvcmtmbG93UXVldWVOYW1lKHdvcmtmbG93TmFtZSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjZUNhcnJpZXI6IGF3YWl0IHNlcmlhbGl6ZVRyYWNlQ2FycmllcigpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVlc3RlZEF0OiBuZXcgRGF0ZSgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXBSZXN1bHQudHlwZSA9PT0gJ2NvbXBsZXRlZCcgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXBSZXN1bHQudHlwZSA9PT0gJ2ZhaWxlZCcgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXBSZXN1bHQudHlwZSA9PT0gJ3NraXBwZWQnXG4gICAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBMb2FkIGV2ZW50cyB0byBjaGVjayBpZiBhbGwgcGFyYWxsZWwgc3RlcHMgYXJlIGRvbmUuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBVc2UgY3Vyc29yLWJhc2VkIGxvYWRpbmcgc28gdGhlIG1haW4gbG9vcCBjYW4gY29udGludWVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluY3JlbWVudGFsbHkgZnJvbSBoZXJlLlxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbG9hZGVkID0gYXdhaXQgbG9hZFdvcmtmbG93UnVuRXZlbnRzKHJ1bklkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhY2hlZEV2ZW50cyA9IGxvYWRlZC5ldmVudHM7XG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudHNDdXJzb3IgPSBsb2FkZWQuY3Vyc29yO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBDaGVjayBmb3IgcGVuZGluZyBzdGVwczogYW55IHN0ZXBfY3JlYXRlZCB3aXRob3V0XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhIG1hdGNoaW5nIHN0ZXBfY29tcGxldGVkIG9yIHN0ZXBfZmFpbGVkLlxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RlcENyZWF0ZWRJZHMgPSBuZXcgU2V0PHN0cmluZyB8IHVuZGVmaW5lZD4oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0ZXBUZXJtaW5hbElkcyA9IG5ldyBTZXQ8c3RyaW5nIHwgdW5kZWZpbmVkPigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBlIG9mIGNhY2hlZEV2ZW50cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZS5ldmVudFR5cGUgPT09ICdzdGVwX2NyZWF0ZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcENyZWF0ZWRJZHMuYWRkKGUuY29ycmVsYXRpb25JZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZS5ldmVudFR5cGUgPT09ICdzdGVwX2NvbXBsZXRlZCcgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLmV2ZW50VHlwZSA9PT0gJ3N0ZXBfZmFpbGVkJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGVwVGVybWluYWxJZHMuYWRkKGUuY29ycmVsYXRpb25JZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBoYXNQZW5kaW5nU3RlcHMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgaWQgb2Ygc3RlcENyZWF0ZWRJZHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzdGVwVGVybWluYWxJZHMuaGFzKGlkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1BlbmRpbmdTdGVwcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGhhc1BlbmRpbmdTdGVwcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPdGhlciBzdGVwcyBzdGlsbCBpbiBwcm9ncmVzcy4gUmV0dXJuIHdpdGhvdXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gcXVldWluZyDigJQgdGhlIGxhc3QgaGFuZGxlciB0byBjb21wbGV0ZSB3aWxsIHNlZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhbGwgc3RlcHMgZG9uZSBhbmQgcmVwbGF5IGlubGluZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5kZWJ1ZyhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQmFja2dyb3VuZCBzdGVwIGRvbmUgYnV0IG90aGVyIHN0ZXBzIHBlbmRpbmcsIHJldHVybmluZycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgeyB3b3JrZmxvd1J1bklkOiBydW5JZCB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWxsIHN0ZXBzIGRvbmUg4oCUIGZhbGwgdGhyb3VnaCB0byB0aGUgbWFpbiByZXBsYXkgbG9vcC5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNldCB1cCBzaGFyZWQgc3RhdGUgc28gdGhlIGxvb3AgY2FuIGNvbnRpbnVlLlxuICAgICAgICAgICAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5kZWJ1ZyhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgJ0FsbCBwYXJhbGxlbCBzdGVwcyBkb25lLCByZXBsYXlpbmcgaW5saW5lIGFmdGVyIGJhY2tncm91bmQgc3RlcCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHsgd29ya2Zsb3dSdW5JZDogcnVuSWQgfVxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuID0gYmdSdW47XG4gICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1N0YXJ0ZWRBdCA9IGJnU3RhcnRlZEF0O1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gY2FjaGVkRXZlbnRzIGFuZCBldmVudHNDdXJzb3IgYWxyZWFkeSBzZXQgZnJvbSBsb2FkIGFib3ZlXG4gICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yQ29kZSA9IGdldFdvcmtmbG93U2V0dXBFcnJvckNvZGUoZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgICBpZiAoIWVycm9yQ29kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICBhd2FpdCByZWNvcmRGYXRhbFJ1bkVycm9yKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdvcmxkLFxuICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVlc3RJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycixcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ29kZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZ01lc3NhZ2U6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICdGYXRhbCBlcnJvciB3aGlsZSBwcmVwYXJpbmcgYmFja2dyb3VuZCB3b3JrZmxvdyBzdGVwJyxcbiAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgLy8gLS0tIEluZnJhc3RydWN0dXJlOiBwcmVwYXJlIHRoZSBydW4gc3RhdGUgLS0tXG4gICAgICAgICAgICAgICAgICAvLyBTa2lwIGlmIHdvcmtmbG93UnVuIHdhcyBhbHJlYWR5IHNldCBieSB0aGUgYmFja2dyb3VuZFxuICAgICAgICAgICAgICAgICAgLy8gc3RlcCBwYXRoIChpbmxpbmUgcmVwbGF5IGFmdGVyIGFsbCBwYXJhbGxlbCBzdGVwcyBkb25lKS5cbiAgICAgICAgICAgICAgICAgIGlmICghd29ya2Zsb3dSdW4pIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gQWx3YXlzIGNhbGwgcnVuX3N0YXJ0ZWQgZGlyZWN0bHkg4oCUIHRoaXMgYm90aCB0cmFuc2l0aW9uc1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGUgcnVuIHRvICdydW5uaW5nJyBBTkQgcmV0dXJucyB0aGUgcnVuIGVudGl0eSwgc2F2aW5nXG4gICAgICAgICAgICAgICAgICAgIC8vIGEgc2VwYXJhdGUgcnVucy5nZXQgcm91bmQtdHJpcC5cbiAgICAgICAgICAgICAgICAgICAgLy8gQ29udHJhY3Q6IGV2ZW50cy5jcmVhdGUoJ3J1bl9zdGFydGVkJykgbXVzdCBiZSBpZGVtcG90ZW50XG4gICAgICAgICAgICAgICAgICAgIC8vIGZvciBydW5zIGFscmVhZHkgaW4gJ3J1bm5pbmcnIHN0YXR1cyAocmV0dXJuIHRoZSBydW5cbiAgICAgICAgICAgICAgICAgICAgLy8gd2l0aG91dCBlcnJvciksIG5vdCBqdXN0IGZvciBwZW5kaW5nIOKGkiBydW5uaW5nIHRyYW5zaXRpb25zLlxuICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUoXG4gICAgICAgICAgICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRUeXBlOiAncnVuX3N0YXJ0ZWQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBVc2UgdGhlIHNwZWMgdmVyc2lvbiBmcm9tIHRoZSBvcmlnaW5hbCBzdGFydCgpIGNhbGxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2hlbiBhdmFpbGFibGUsIHNvIHRoZSByZXNpbGllbnQgc3RhcnQgcGF0aCBjcmVhdGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBydW4gd2l0aCB0aGUgY29ycmVjdCB2ZXJzaW9uIChub3QgYWx3YXlzIGN1cnJlbnQpLlxuICAgICAgICAgICAgICAgICAgICAgICAgICBzcGVjVmVyc2lvbjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBydW5JbnB1dD8uc3BlY1ZlcnNpb24gPz8gU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFBhc3MgcnVuIGlucHV0IGZyb20gcXVldWUgc28gdGhlIHNlcnZlciBjYW5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gY3JlYXRlIHRoZSBydW4gaWYgcnVuX2NyZWF0ZWQgd2FzIG1pc3NlZC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVWludDhBcnJheSB2YWx1ZXMgc3Vydml2ZSB0aGUgcXVldWUgbmF0aXZlbHlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gKENCT1Igb24gd29ybGQtdmVyY2VsLCBKU09OIHJldml2ZXIgb24gd29ybGQtbG9jYWwpLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAuLi4ocnVuSW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQ6IHJ1bklucHV0LmlucHV0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlcGxveW1lbnRJZDogcnVuSW5wdXQuZGVwbG95bWVudElkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93TmFtZTogcnVuSW5wdXQud29ya2Zsb3dOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4ZWN1dGlvbkNvbnRleHQ6IHJ1bklucHV0LmV4ZWN1dGlvbkNvbnRleHQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgOiB7fSksXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgeyByZXF1ZXN0SWQgfVxuICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgaWYgKCFyZXN1bHQucnVuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgV29ya2Zsb3dSdW50aW1lRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGBFdmVudCBjcmVhdGlvbiBmb3IgJ3J1bl9zdGFydGVkJyBkaWQgbm90IHJldHVybiB0aGUgcnVuIGVudGl0eSBmb3IgcnVuIFwiJHtydW5JZH1cImBcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuID0gcmVzdWx0LnJ1bjtcblxuICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSByZXNwb25zZSBpbmNsdWRlcyBldmVudHMsIHVzZSB0aGVtIHRvIHNraXBcbiAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgaW5pdGlhbCBldmVudHMubGlzdCBjYWxsIGFuZCByZWR1Y2UgVFRGQi5cbiAgICAgICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuZXZlbnRzICYmXG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQuZXZlbnRzLmxlbmd0aCA+IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5oYXNNb3JlICE9PSB0cnVlXG4gICAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcmVsb2FkZWRFdmVudHMgPSByZXN1bHQuZXZlbnRzO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJlbG9hZGVkRXZlbnRzQ3Vyc29yID0gcmVzdWx0LmN1cnNvcjtcbiAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICBpZiAoIXdvcmtmbG93UnVuLnN0YXJ0ZWRBdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFdvcmtmbG93UnVudGltZUVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgICBgV29ya2Zsb3cgcnVuIFwiJHtydW5JZH1cIiBoYXMgbm8gXCJzdGFydGVkQXRcIiB0aW1lc3RhbXBgXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgLy8gUnVuIHdhcyBjb25jdXJyZW50bHkgY29tcGxldGVkL2ZhaWxlZC9jYW5jZWxsZWRcbiAgICAgICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICBFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIFJ1bkV4cGlyZWRFcnJvci5pcyhlcnIpXG4gICAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBFbnRpdHlDb25mbGljdEVycm9yOiBydW4gd2FzIGNvbmN1cnJlbnRseVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gY29tcGxldGVkL2ZhaWxlZC9jYW5jZWxsZWQgZHVyaW5nIHNldHVwLlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gUnVuRXhwaXJlZEVycm9yOiBydW4gYWxyZWFkeSBpbiB0ZXJtaW5hbCBzdGF0ZS5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEluIGJvdGggY2FzZXMsIHNraXAgcHJvY2Vzc2luZyB0aGlzIG1lc3NhZ2UuXG4gICAgICAgICAgICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICAgICAgICAgICAgICdSdW4gYWxyZWFkeSBmaW5pc2hlZCBkdXJpbmcgc2V0dXAsIHNraXBwaW5nJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgeyB3b3JrZmxvd1J1bklkOiBydW5JZCwgbWVzc2FnZTogZXJyLm1lc3NhZ2UgfVxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3JDb2RlID0gZ2V0V29ya2Zsb3dTZXR1cEVycm9yQ29kZShlcnIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFlcnJvckNvZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgcmVjb3JkRmF0YWxSdW5FcnJvcih7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmxkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVlc3RJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNvZGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGxvZ01lc3NhZ2U6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0ZhdGFsIHJ1bnRpbWUgZXJyb3IgZHVyaW5nIHdvcmtmbG93IHNldHVwJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHdvcmtmbG93U3RhcnRlZEF0ID0gK3dvcmtmbG93UnVuLnN0YXJ0ZWRBdDtcblxuICAgICAgICAgICAgICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dSdW5TdGF0dXMod29ya2Zsb3dSdW4uc3RhdHVzKSxcbiAgICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dTdGFydGVkQXQod29ya2Zsb3dTdGFydGVkQXQpLFxuICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAod29ya2Zsb3dSdW4uc3RhdHVzICE9PSAncnVubmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAvLyBXb3JrZmxvdyBoYXMgYWxyZWFkeSBjb21wbGV0ZWQgb3IgZmFpbGVkLCBzbyB3ZSBjYW4gc2tpcCBpdFxuICAgICAgICAgICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgICAgICAgICAgICdXb3JrZmxvdyBhbHJlYWR5IGNvbXBsZXRlZCBvciBmYWlsZWQsIHNraXBwaW5nJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXR1czogd29ya2Zsb3dSdW4uc3RhdHVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAvLyBUT0RPOiBmb3IgYGNhbmNlbGAsIHdlIGFjdHVhbGx5IHdhbnQgdG8gcHJvcGFnYXRlIGEgV29ya2Zsb3dDYW5jZWxsZWQgZXZlbnRcbiAgICAgICAgICAgICAgICAgICAgICAvLyBpbnNpZGUgdGhlIHdvcmtmbG93IGNvbnRleHQgc28gdGhlIHVzZXIgY2FuIGdyYWNlZnVsbHkgZXhpdC4gdGhpcyBpcyBTSUdURVJNXG4gICAgICAgICAgICAgICAgICAgICAgLy8gVE9ETzogZnVydGhlcm1vcmUsIHRoZXJlIHNob3VsZCBiZSBhIHRpbWVvdXQgb3IgYSB3YXkgdG8gZm9yY2UgY2FuY2VsIFNJR0tJTExcbiAgICAgICAgICAgICAgICAgICAgICAvLyBzbyB0aGF0IHdlIGFjdHVhbGx5IGV4aXQgaGVyZSB3aXRob3V0IHJlcGxheWluZyB0aGUgd29ya2Zsb3cgYXQgYWxsLCBpbiB0aGUgY2FzZVxuICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSByZXBsYXlpbmcgdGhlIHdvcmtmbG93IGlzIGl0c2VsZiBmYWlsaW5nLlxuXG4gICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9IC8vIGVuZCBpZiAoIXdvcmtmbG93UnVuKVxuXG4gICAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIHRoZSBlbmNyeXB0aW9uIGtleSBmb3IgdGhpcyBydW4ncyBkZXBsb3ltZW50LlxuICAgICAgICAgICAgICAgICAgLy8gVXNlZCBlYWdlcmx5IGhlcmUgc2luY2UgYm90aCBydW5Xb3JrZmxvdyAoaW5wdXRcbiAgICAgICAgICAgICAgICAgIC8vIGh5ZHJhdGlvbiAvIGhvb2sgcGF5bG9hZCBkZWNyeXB0aW9uKSBhbmQgdGhlIHJ1bl9mYWlsZWRcbiAgICAgICAgICAgICAgICAgIC8vIGRlaHlkcmF0ZSBwYXRoIGJlbG93IG5lZWQgaXQuIE1lbW9pemVkIGFjY2Vzc29yOiBmaXJzdFxuICAgICAgICAgICAgICAgICAgLy8gY2FsbCB0cmlnZ2VycyB0aGUgYWN0dWFsIGZldGNoIC8gSEtERiBkZXJpdmF0aW9uLFxuICAgICAgICAgICAgICAgICAgLy8gc3Vic2VxdWVudCBjYWxscyBhd2FpdCB0aGUgY2FjaGVkIHByb21pc2UuXG4gICAgICAgICAgICAgICAgICBjb25zdCBnZXRFbmNyeXB0aW9uS2V5ID0gbWVtb2l6ZUVuY3J5cHRpb25LZXkoXG4gICAgICAgICAgICAgICAgICAgIHdvcmxkLFxuICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1blxuICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGVuY3J5cHRpb25LZXkgPSBhd2FpdCBnZXRFbmNyeXB0aW9uS2V5KCk7XG5cbiAgICAgICAgICAgICAgICAgIC8vIE1haW4gcmVwbGF5IGxvb3BcbiAgICAgICAgICAgICAgICAgIC8vIGJpb21lLWlnbm9yZSBsaW50L2NvcnJlY3RuZXNzL25vQ29uc3RhbnRDb25kaXRpb246IGludGVudGlvbmFsIGxvb3BcbiAgICAgICAgICAgICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGxvb3BJdGVyYXRpb24rKztcblxuICAgICAgICAgICAgICAgICAgICAvLyBSZXBsYXktYnVkZ2V0IGNoZWNrOiBiYWlsIG91dCAocmV0cnkgb3IgZmFpbCkgaWZcbiAgICAgICAgICAgICAgICAgICAgLy8gbm9uLXN0ZXAgdGltZSB3aXRoaW4gdGhpcyBpbnZvY2F0aW9uIGhhcyBleGNlZWRlZFxuICAgICAgICAgICAgICAgICAgICAvLyB0aGUgY29uZmlndXJlZCBidWRnZXQuIFN0ZXAgYm9kaWVzIGFyZSBleGNsdWRlZFxuICAgICAgICAgICAgICAgICAgICAvLyBiZWNhdXNlIHJlcGxheUJ1ZGdldC5wYXVzZSgpL3Jlc3VtZSgpIGJyYWNrZXQgZXZlcnlcbiAgICAgICAgICAgICAgICAgICAgLy8gYGV4ZWN1dGVTdGVwYCBjYWxsLlxuICAgICAgICAgICAgICAgICAgICBpZiAocmVwbGF5QnVkZ2V0LmlzRXhoYXVzdGVkKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBoYW5kbGVSZXBsYXlCdWRnZXRFeGhhdXN0ZWQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd05hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICByZXF1ZXN0SWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBhdHRlbXB0OiBtZXRhZGF0YS5hdHRlbXB0LFxuICAgICAgICAgICAgICAgICAgICAgICAgbGltaXRNczogcmVwbGF5QnVkZ2V0LmNvbmZpZ3VyZWRMaW1pdE1zLFxuICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgIC8vIE9uIFZlcmNlbCwgaGFuZGxlUmVwbGF5QnVkZ2V0RXhoYXVzdGVkIGFsd2F5c1xuICAgICAgICAgICAgICAgICAgICAgIC8vIGV4aXRzIHRoZSBwcm9jZXNzLiBPbiBsb2NhbCBkZXYgaXQgcmV0dXJuczsgd2VcbiAgICAgICAgICAgICAgICAgICAgICAvLyBmYWxsIHRocm91Z2ggYW5kIHRoZSByZXF1ZXN0IGVuZHMgbm9ybWFsbHlcbiAgICAgICAgICAgICAgICAgICAgICAvLyAocnVuX2ZhaWxlZCBoYXMgYmVlbiB3cml0dGVuIGJlc3QtZWZmb3J0KS5cbiAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBDaGVjayB0aW1lb3V0IGJlZm9yZSByZXBsYXlcbiAgICAgICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICAgIERhdGUubm93KCkgLSBpbnZvY2F0aW9uU3RhcnRUaW1lID49XG4gICAgICAgICAgICAgICAgICAgICAgTk9fSU5MSU5FX1JFUExBWV9BRlRFUl9NU1xuICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICAgICAgICAgICAnVjIgdGltZW91dCByZWFjaGVkLCByZS1zY2hlZHVsaW5nIHdvcmtmbG93JyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGxvb3BJdGVyYXRpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGVsYXBzZWRNczogRGF0ZS5ub3coKSAtIGludm9jYXRpb25TdGFydFRpbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBxdWV1ZU1lc3NhZ2UoXG4gICAgICAgICAgICAgICAgICAgICAgICB3b3JsZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGdldFdvcmtmbG93UXVldWVOYW1lKHdvcmtmbG93TmFtZSksXG4gICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjZUNhcnJpZXI6IGF3YWl0IHNlcmlhbGl6ZVRyYWNlQ2FycmllcigpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICByZXF1ZXN0ZWRBdDogbmV3IERhdGUoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGxldCByZXBsYXlTdGFydCA9IDA7XG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgLy8gTG9hZCBldmVudHMg4oCUIHVzZSBjYWNoZWQgZXZlbnRzIHdpdGggaW5jcmVtZW50YWwgZmV0Y2ggb24gc3Vic2VxdWVudCBpdGVyYXRpb25zLlxuICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZSBzZXJ2ZXIgYWx3YXlzIHJldHVybnMgYSBjdXJzb3Igd2hlbiB0aGVyZSBhcmUgZXZlbnRzIChldmVuIG9uIHRoZVxuICAgICAgICAgICAgICAgICAgICAgIC8vIGZpbmFsIHBhZ2UpLCBzbyB3ZSBjYW4gcmVsaWFibHkgdXNlIGl0IGZvciBpbmNyZW1lbnRhbCBsb2FkaW5nLlxuICAgICAgICAgICAgICAgICAgICAgIGxldCBldmVudHM6IEV2ZW50W107XG4gICAgICAgICAgICAgICAgICAgICAgaWYgKGNhY2hlZEV2ZW50cyA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRmlyc3QgaXRlcmF0aW9uOiB1c2UgcHJlbG9hZGVkIGV2ZW50cyBpZiBhdmFpbGFibGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBvdGhlcndpc2UgZG8gYSBmdWxsIGxvYWQgd2l0aCBjdXJzb3IuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJlbG9hZGVkRXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cyA9IHByZWxvYWRlZEV2ZW50cztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzQ3Vyc29yID0gcHJlbG9hZGVkRXZlbnRzQ3Vyc29yID8/IG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBsb2FkZWQgPSBhd2FpdCBsb2FkV29ya2Zsb3dSdW5FdmVudHMocnVuSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMgPSBsb2FkZWQuZXZlbnRzO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHNDdXJzb3IgPSBsb2FkZWQuY3Vyc29yO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZXZlbnRzQ3Vyc29yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBTdWJzZXF1ZW50IGl0ZXJhdGlvbjogZmV0Y2ggb25seSBuZXcgZXZlbnRzIHNpbmNlIGxhc3QgY3Vyc29yXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBsb2FkZWQgPSBhd2FpdCBsb2FkV29ya2Zsb3dSdW5FdmVudHMoXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHNDdXJzb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBEZWR1cGUgYnkgZXZlbnRJZDogYSBwcmV2aW91cyBpdGVyYXRpb24gbWF5IGhhdmVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFwcGVuZGVkIGEgcmVmcmVzaGVkIHdhaXQtY29tcGxldGlvbiBkZWx0YSBiZWZvcmVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBuZXh0IGxvb3Agb2JzZXJ2ZXMgdGhlIGFkdmFuY2VkIGN1cnNvciwgc28gYW5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluY3JlbWVudGFsIGZldGNoIGNhbiByZXR1cm4gZXZlbnRzIHdlIGFscmVhZHkgaGF2ZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbG9jYWxseS5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsb2FkZWQuZXZlbnRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXhpc3RpbmdJZHMgPSBuZXcgU2V0KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhY2hlZEV2ZW50cy5tYXAoKGUpID0+IGUuZXZlbnRJZClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBlIG9mIGxvYWRlZC5ldmVudHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWV4aXN0aW5nSWRzLmhhcyhlLmV2ZW50SWQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGlzdGluZ0lkcy5hZGQoZS5ldmVudElkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhY2hlZEV2ZW50cy5wdXNoKGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzQ3Vyc29yID0gbG9hZGVkLmN1cnNvciA/PyBldmVudHNDdXJzb3I7XG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudHMgPSBjYWNoZWRFdmVudHM7XG4gICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmVsb2FkZWRFdmVudHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGlvbiAyIGFmdGVyIGl0ZXJhdGlvbiAxIHVzZWQgcHJlbG9hZGVkIGV2ZW50c1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gKHdoaWNoIGRvbid0IGNhcnJ5IGEgY3Vyc29yKS4gRG8gYSBmdWxsIGxvYWQgbm93IHRvXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBwaWNrIHVwIGFueSBldmVudHMgd3JpdHRlbiBzaW5jZSB0aGUgcHJlbG9hZGVkIHNldFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYW5kIG9idGFpbiBhIGN1cnNvciBmb3Igc3Vic2VxdWVudCBpbmNyZW1lbnRhbFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbG9hZHMuIFRoaXMgaXMgdGhlIGV4cGVjdGVkIHBhdGgsIG5vdCBhIGJ1Zy5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuZGVidWcoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICdObyBjdXJzb3IgYWZ0ZXIgcHJlbG9hZGVkLWV2ZW50cyBmaXJzdCBpdGVyYXRpb247IGRvaW5nIGZ1bGwgcmVsb2FkIHRvIHBpY2sgdXAgY3Vyc29yLicsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHsgd29ya2Zsb3dSdW5JZDogcnVuSWQgfVxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGxvYWRlZCA9IGF3YWl0IGxvYWRXb3JrZmxvd1J1bkV2ZW50cyhydW5JZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYWNoZWRFdmVudHMgPSBsb2FkZWQuZXZlbnRzO1xuICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzQ3Vyc29yID0gbG9hZGVkLmN1cnNvcjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cyA9IGNhY2hlZEV2ZW50cztcbiAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTm8gY3Vyc29yIGF2YWlsYWJsZSBkZXNwaXRlIGhhdmluZyBjYWNoZWQgZXZlbnRzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhbmQgbm8gcHJlbG9hZGVkLWV2ZW50cyBleHBsYW5hdGlvbi4gQWxsIFdvcmxkXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpbXBsZW1lbnRhdGlvbnMgYXJlIHJlcXVpcmVkIHRvIHJldHVybiBhIGN1cnNvclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2hlbiB0aGVyZSBhcmUgZXZlbnRzLCBzbyB0aGlzIHNpZ25hbHMgYSBidWcgaW5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBXb3JsZC4gRmFsbCBiYWNrIHRvIGEgZnVsbCByZWxvYWQgdG8gYXZvaWRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHN0YWxlIGRhdGEuXG4gICAgICAgICAgICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLndhcm4oXG4gICAgICAgICAgICAgICAgICAgICAgICAgICdFdmVudCBjdXJzb3IgbWlzc2luZyBhZnRlciBpbml0aWFsIGxvYWQg4oCUIGZhbGxpbmcgYmFjayB0byBmdWxsIHJlbG9hZC4gJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ1RoaXMgaW5kaWNhdGVzIGEgYnVnIGluIHRoZSBXb3JsZCBpbXBsZW1lbnRhdGlvbi4nLFxuICAgICAgICAgICAgICAgICAgICAgICAgICB7IHdvcmtmbG93UnVuSWQ6IHJ1bklkIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBsb2FkZWQgPSBhd2FpdCBsb2FkV29ya2Zsb3dSdW5FdmVudHMocnVuSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FjaGVkRXZlbnRzID0gbG9hZGVkLmV2ZW50cztcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50c0N1cnNvciA9IGxvYWRlZC5jdXJzb3I7XG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudHMgPSBjYWNoZWRFdmVudHM7XG4gICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgLy8gRGV0ZWN0IGNvbmN1cnJlbnQgY29tcGxldGlvbiB2aWEgdGhlIGV2ZW50IGxvZzogaWZcbiAgICAgICAgICAgICAgICAgICAgICAvLyBhbnkgb3RoZXIgaGFuZGxlciB3cm90ZSBhIHRlcm1pbmFsIHJ1biBldmVudCwgZXhpdFxuICAgICAgICAgICAgICAgICAgICAgIC8vIGJlZm9yZSBkb2luZyByZXBsYXkgd29yay4gVGhlIHJ1biBlbnRpdHkncyBzdGF0dXMgaXNcbiAgICAgICAgICAgICAgICAgICAgICAvLyBkZXJpdmVkIGZyb20gdGhlc2UgZXZlbnRzLCBzbyBjaGVja2luZyB0aGUgbG9nIGhlcmVcbiAgICAgICAgICAgICAgICAgICAgICAvLyBnaXZlcyB1cyB0aGUgc2FtZSBzaWduYWwgYXMgYSBydW5zLmdldCgpIHJvdW5kLXRyaXBcbiAgICAgICAgICAgICAgICAgICAgICAvLyB3aXRob3V0IHRoZSBleHRyYSByZXF1ZXN0IHBlciBsb29wIGl0ZXJhdGlvbi5cbiAgICAgICAgICAgICAgICAgICAgICAvLyBUZXJtaW5hbCBydW4gZXZlbnRzIGFyZSBhbHdheXMgbGFzdCBieSBjb25zdHJ1Y3Rpb25cbiAgICAgICAgICAgICAgICAgICAgICAvLyAobm8gZXZlbnQgY3JlYXRpb24gc3VjY2VlZHMgYWdhaW5zdCBhIHRlcm1pbmFsIHJ1biksXG4gICAgICAgICAgICAgICAgICAgICAgLy8gYnV0IHNjYW4gdGhlIGZ1bGwgYXJyYXkgZm9yIGRlZmVuc2UtaW4tZGVwdGg6IGFcbiAgICAgICAgICAgICAgICAgICAgICAvLyBXb3JsZC9iYWNrZW5kIG9yZGVyaW5nIGJ1ZyBzaG91bGRuJ3QgbWFrZSB1cyBtaXNzXG4gICAgICAgICAgICAgICAgICAgICAgLy8gYW4gYWN0dWFsIHRlcm1pbmF0aW9uIHNpZ25hbC5cbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0ZXJtaW5hbFJ1bkV2ZW50ID0gZXZlbnRzLmZpbmQoXG4gICAgICAgICAgICAgICAgICAgICAgICAoZSkgPT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgZS5ldmVudFR5cGUgPT09ICdydW5fY29tcGxldGVkJyB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICBlLmV2ZW50VHlwZSA9PT0gJ3J1bl9mYWlsZWQnIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGUuZXZlbnRUeXBlID09PSAncnVuX2NhbmNlbGxlZCdcbiAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgIGlmICh0ZXJtaW5hbFJ1bkV2ZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmRlYnVnKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAnUnVuIGNvbXBsZXRlZCBieSBjb25jdXJyZW50IGhhbmRsZXIsIGV4aXRpbmcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRUeXBlOiB0ZXJtaW5hbFJ1bkV2ZW50LmV2ZW50VHlwZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAvLyBDb21wbGV0ZSBlbGFwc2VkIHdhaXRzXG4gICAgICAgICAgICAgICAgICAgICAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb21wbGV0ZWRXYWl0SWRzID0gbmV3IFNldChcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAuZmlsdGVyKChlKSA9PiBlLmV2ZW50VHlwZSA9PT0gJ3dhaXRfY29tcGxldGVkJylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLm1hcCgoZSkgPT4gZS5jb3JyZWxhdGlvbklkKVxuICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgY29uc3Qgd2FpdHNUb0NvbXBsZXRlID0gZXZlbnRzXG4gICAgICAgICAgICAgICAgICAgICAgICAuZmlsdGVyKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZVxuICAgICAgICAgICAgICAgICAgICAgICAgICApOiBlIGlzIEV4dHJhY3Q8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgeyBldmVudFR5cGU6ICd3YWl0X2NyZWF0ZWQnIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPiAmIHsgY29ycmVsYXRpb25JZDogc3RyaW5nIH0gPT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLmV2ZW50VHlwZSA9PT0gJ3dhaXRfY3JlYXRlZCcgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlLmNvcnJlbGF0aW9uSWQgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICFjb21wbGV0ZWRXYWl0SWRzLmhhcyhlLmNvcnJlbGF0aW9uSWQpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm93ID49IChlLmV2ZW50RGF0YS5yZXN1bWVBdCBhcyBEYXRlKS5nZXRUaW1lKClcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgIC5tYXAoKGUpID0+ICh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50VHlwZTogJ3dhaXRfY29tcGxldGVkJyBhcyBjb25zdCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBlLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VtZUF0OiBlLmV2ZW50RGF0YS5yZXN1bWVBdCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pKTtcblxuICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qgd2FpdEV2ZW50IG9mIHdhaXRzVG9Db21wbGV0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgd29ybGQuZXZlbnRzLmNyZWF0ZShydW5JZCwgd2FpdEV2ZW50LCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWVzdElkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ1dhaXQgYWxyZWFkeSBjb21wbGV0ZWQsIHNraXBwaW5nJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHdhaXRFdmVudC5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgIGlmICh3YWl0c1RvQ29tcGxldGUubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlIGV2ZW50IGxpc3QgYWJvdmUgbWF5IGJlIHN0YWxlIGJ5IHRoZSB0aW1lIGFuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBlbGFwc2VkIHdhaXQgaXMgY29tbWl0dGVkLiBMb2FkIG9ubHkgZXZlbnRzIGFmdGVyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgb3JpZ2luYWwgc25hcHNob3QgY3Vyc29yIHNvIGNvbmN1cnJlbnQgZHVyYWJsZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZXZlbnRzLCBzdWNoIGFzIGhvb2tfcmVjZWl2ZWQsIGtlZXAgdGhlaXIgb3JkZXJpbmdcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJlbGF0aXZlIHRvIHdhaXRfY29tcGxldGVkLiBGYWxsIGJhY2sgdG8gYSBmdWxsXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyByZWxvYWQgZm9yIG9sZGVyIHdvcmxkcyB0aGF0IGNhbm5vdCBnaXZlIHVzIGEgc3RhYmxlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjdXJzb3IsIG9yIGlmIHRoZSBjdXJzb3IgZGVsdGEgZG9lcyBub3QgaW5jbHVkZSB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdhaXQgY29tcGxldGlvbiB0aGlzIGhhbmRsZXIganVzdCBhdHRlbXB0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXZlbnRzQ3Vyc29yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGxvYWRlZCA9IGF3YWl0IGxvYWRXb3JrZmxvd1J1bkV2ZW50cyhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHNDdXJzb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY29tcGxldGVkV2FpdElkc0FmdGVyQ3Vyc29yID0gbmV3IFNldChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2FkZWQuZXZlbnRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZmlsdGVyKChlKSA9PiBlLmV2ZW50VHlwZSA9PT0gJ3dhaXRfY29tcGxldGVkJylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5tYXAoKGUpID0+IGUuY29ycmVsYXRpb25JZClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2F3QWxsV2FpdENvbXBsZXRpb25zID0gd2FpdHNUb0NvbXBsZXRlLmV2ZXJ5KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICh3YWl0RXZlbnQpID0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wbGV0ZWRXYWl0SWRzQWZ0ZXJDdXJzb3IuaGFzKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3YWl0RXZlbnQuY29ycmVsYXRpb25JZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzYXdBbGxXYWl0Q29tcGxldGlvbnMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBleGlzdGluZ0lkcyA9IG5ldyBTZXQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMubWFwKChlKSA9PiBlLmV2ZW50SWQpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGV2ZW50IG9mIGxvYWRlZC5ldmVudHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZXhpc3RpbmdJZHMuaGFzKGV2ZW50LmV2ZW50SWQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4aXN0aW5nSWRzLmFkZChldmVudC5ldmVudElkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzLnB1c2goZXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHNDdXJzb3IgPSBsb2FkZWQuY3Vyc29yID8/IGV2ZW50c0N1cnNvcjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBsb2FkZWQgPSBhd2FpdCBsb2FkV29ya2Zsb3dSdW5FdmVudHMocnVuSWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50cyA9IGxvYWRlZC5ldmVudHM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzQ3Vyc29yID0gbG9hZGVkLmN1cnNvcjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbG9hZGVkID0gYXdhaXQgbG9hZFdvcmtmbG93UnVuRXZlbnRzKHJ1bklkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzID0gbG9hZGVkLmV2ZW50cztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzQ3Vyc29yID0gbG9hZGVkLmN1cnNvcjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAvLyBVcGRhdGUgY2FjaGUgcmVmZXJlbmNlIChtYXkgaGF2ZSBiZWVuIHNldCBmb3IgZmlyc3QgdGltZSlcbiAgICAgICAgICAgICAgICAgICAgICBjYWNoZWRFdmVudHMgPSBldmVudHM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAvLyBSZXBsYXkgd29ya2Zsb3dcbiAgICAgICAgICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmRlYnVnKCdTdGFydGluZyB3b3JrZmxvdyByZXBsYXknLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvb3BJdGVyYXRpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudENvdW50OiBldmVudHMubGVuZ3RoLFxuICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgIHJlcGxheVN0YXJ0ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBydW5Xb3JrZmxvdyhcbiAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93Q29kZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgZW5jcnlwdGlvbktleVxuICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5kZWJ1ZygnV29ya2Zsb3cgcmVwbGF5IGNvbXBsZXRlZCcsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgbG9vcEl0ZXJhdGlvbixcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlcGxheU1zOiBEYXRlLm5vdygpIC0gcmVwbGF5U3RhcnQsXG4gICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAvLyBXb3JrZmxvdyBjb21wbGV0ZWRcbiAgICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgd29ybGQuZXZlbnRzLmNyZWF0ZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudFR5cGU6ICdydW5fY29tcGxldGVkJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnREYXRhOiB7IG91dHB1dDogcmVzdWx0IH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHsgcmVxdWVzdElkIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgIEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICBSdW5FeHBpcmVkRXJyb3IuaXMoZXJyKVxuICAgICAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnVHJpZWQgY29tcGxldGluZyB3b3JrZmxvdyBydW4sIGJ1dCBydW4gaGFzIGFscmVhZHkgZmluaXNoZWQuJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7IHdvcmtmbG93UnVuSWQ6IHJ1bklkLCBtZXNzYWdlOiBlcnIubWVzc2FnZSB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICBzcGFuPy5zZXRBdHRyaWJ1dGVzKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1J1blN0YXR1cygnY29tcGxldGVkJyksXG4gICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICBpZiAoV29ya2Zsb3dTdXNwZW5zaW9uLmlzKGVycikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuZGVidWcoJ1dvcmtmbG93IHN1c3BlbmRlZCcsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGxvb3BJdGVyYXRpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJlcGxheU1zOiBEYXRlLm5vdygpIC0gcmVwbGF5U3RhcnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXBzOiBlcnIuc3RlcENvdW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICBob29rczogZXJyLmhvb2tDb3VudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgd2FpdHM6IGVyci53YWl0Q291bnQsXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN1c3BlbnNpb25NZXNzYWdlID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgYnVpbGRXb3JrZmxvd1N1c3BlbnNpb25NZXNzYWdlKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVyci5zdGVwQ291bnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyLmhvb2tDb3VudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnIud2FpdENvdW50XG4gICAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3VzcGVuc2lvbk1lc3NhZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5kZWJ1ZyhzdXNwZW5zaW9uTWVzc2FnZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFYyOiBoYW5kbGUgc3VzcGVuc2lvbiB3aXRob3V0IHF1ZXVpbmcgc3RlcHNcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN1c3BlbnNpb25TdGFydCA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdXNwZW5zaW9uUmVzdWx0ID0gYXdhaXQgaGFuZGxlU3VzcGVuc2lvbih7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHN1c3BlbnNpb246IGVycixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgd29ybGQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bjogd29ya2Zsb3dSdW4sXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHNwYW4sXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVlc3RJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5kZWJ1ZygnU3VzcGVuc2lvbiBoYW5kbGVkJywge1xuICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3VzcGVuc2lvbk1zOiBEYXRlLm5vdygpIC0gc3VzcGVuc2lvblN0YXJ0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICBwZW5kaW5nU3RlcHM6IHN1c3BlbnNpb25SZXN1bHQucGVuZGluZ1N0ZXBzLmxlbmd0aCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdGltZW91dFNlY29uZHM6IHN1c3BlbnNpb25SZXN1bHQudGltZW91dFNlY29uZHMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGhhc0hvb2tDb25mbGljdDogc3VzcGVuc2lvblJlc3VsdC5oYXNIb29rQ29uZmxpY3QsXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSG9vayBjb25mbGljdDogYnJlYWsgbG9vcCwgcmUtaW52b2tlIHZpYSBxdWV1ZVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN1c3BlbnNpb25SZXN1bHQuaGFzSG9va0NvbmZsaWN0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7IHRpbWVvdXRTZWNvbmRzOiAwIH07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBlbmRpbmdTdGVwcyA9IHN1c3BlbnNpb25SZXN1bHQucGVuZGluZ1N0ZXBzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocGVuZGluZ1N0ZXBzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBObyBzdGVwcyDigJQgb25seSB3YWl0cy9ob29rc1xuICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3VzcGVuc2lvblJlc3VsdC50aW1lb3V0U2Vjb25kcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpbWVvdXRTZWNvbmRzOiBzdXNwZW5zaW9uUmVzdWx0LnRpbWVvdXRTZWNvbmRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBJbmxpbmUgZXhlY3V0aW9uIGlzIGdhdGVkIG9uIG93bmVyc2hpcDogb25seSB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGhhbmRsZXIgdGhhdCBhY3R1YWxseSB3cm90ZSB0aGUgc3RlcF9jcmVhdGVkIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBtYXkgcnVuIHRoZSBzdGVwIGJvZHkgaW5saW5lLiBUaGUgd29ybGQtbGV2ZWxcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHN0ZXBfY3JlYXRlZCBpcyBhdG9taWMgcGVyLWNvcnJlbGF0aW9uSWQsIHNvXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBleGFjdGx5IG9uZSBoYW5kbGVyIG93bnMgZWFjaCBzdGVwIOKAlCBjb25jdXJyZW50XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBoYW5kbGVycyBjYW4ndCByYWNlIG9uIHN0ZXAgZXhlY3V0aW9uLlxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3duZWRQZW5kaW5nU3RlcHMgPSBwZW5kaW5nU3RlcHMuZmlsdGVyKChzKSA9PlxuICAgICAgICAgICAgICAgICAgICAgICAgICBzdXNwZW5zaW9uUmVzdWx0LmNyZWF0ZWRTdGVwQ29ycmVsYXRpb25JZHMuaGFzKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHMuY29ycmVsYXRpb25JZFxuICAgICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBQaWNrIG9uZSBvd25lZCBzdGVwIHRvIGV4ZWN1dGUgaW5saW5lIChpZiBhbnkpLlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlIHJlc3Qgb2YgdGhlIHBlbmRpbmcgc3RlcHMgYXJlIHF1ZXVlZCBiZWxvdy5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBTa2lwIGlubGluZSBleGVjdXRpb24gZW50aXJlbHkgd2hlbiB0aGUgc3VzcGVuc2lvblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWxzbyBoYXMgYSBwZW5kaW5nIHdhaXQgKHNsZWVwKTogYW4gaW5saW5lIGBhd2FpdFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZXhlY3V0ZVN0ZXAoLi4uKWAgYmxvY2tzIHRoZSBoYW5kbGVyIGZvciB0aGUgZnVsbFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc3RlcCBkdXJhdGlvbiwgc28gdGhlIHdhaXQgdGltZXIgbmV2ZXIgaGFzIGEgY2hhbmNlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0byBmaXJlIG9uIHRpbWUuIFRoYXQgZGVmZWF0cyBgUHJvbWlzZS5yYWNlKHN0ZXAsXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzbGVlcClgIHNlbWFudGljcyDigJQgaWYgdGhlIHNsZWVwIGlzIHNob3J0ZXIgdGhhblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIHN0ZXAsIHJlcGxheSBzdGlsbCBwaWNrcyB0aGUgc3RlcCBiZWNhdXNlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB3YWl0X2NvbXBsZXRlZCBpcyBvbmx5IGNyZWF0ZWQgb24gdGhlICpuZXh0KiBsb29wXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpdGVyYXRpb24sIHdoaWNoIGRvZXNuJ3QgcnVuIHVudGlsIHRoZSBzdGVwXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBmaW5pc2hlcy4gUXVldWVpbmcgZXZlcnkgc3RlcCBpbiB0aGlzIGNhc2UgbGV0c1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIHdhaXQgdGltZW91dCBkcml2ZSBhIGNvbnRpbnVhdGlvbiBpbiBwYXJhbGxlbCxcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG1hdGNoaW5nIFYxJ3MgYmVoYXZpb3Igd2hlcmUgZWFjaCBzdGVwIHJhbiBpbiBhXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzZXBhcmF0ZSBmdW5jdGlvbiBpbnZvY2F0aW9uLlxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaW5saW5lU3RlcDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfCAodHlwZW9mIHBlbmRpbmdTdGVwcylbbnVtYmVyXVxuICAgICAgICAgICAgICAgICAgICAgICAgICB8IHVuZGVmaW5lZCA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHN1c3BlbnNpb25SZXN1bHQudGltZW91dFNlY29uZHMgPT09IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gb3duZWRQZW5kaW5nU3RlcHNbMF1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gUXVldWUgZXZlcnkgcGVuZGluZyBzdGVwIGV4Y2VwdCB0aGUgb25lIHdlJ3JlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBleGVjdXRpbmcgaW5saW5lLiBUaGlzIG1pcnJvcnMgVjEncyB1bmNvbmRpdGlvbmFsXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBlbnF1ZXVlLXdpdGgtaWRlbXBvdGVuY3kgcGF0dGVybiBhbmQgaXMgd2hhdCBtYWtlc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gY3Jhc2ggcmVjb3Zlcnkgd29yazogaWYgYSBwcmlvciBoYW5kbGVyIHdyb3RlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzdGVwX2NyZWF0ZWQgZXZlbnRzIGJ1dCBjcmFzaGVkIGJlZm9yZSBlbnF1ZXVpbmcsXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhIGxhdGVyIGhhbmRsZXIgKGUuZy4sIGZyb20gZmxvdy1tZXNzYWdlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyByZWRlbGl2ZXJ5IG9yIHJlZW5xdWV1ZUFjdGl2ZVJ1bnMpIHdpbGwgZW5xdWV1ZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIG9ycGhhbmVkIHN0ZXBzLiBJbiB0aGUgaGFwcHkgcGF0aCB3aXRoIGFcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNpbmdsZSBvd25lciwgY29uY3VycmVudCBoYW5kbGVycycgcXVldWUgYXR0ZW1wdHNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRlZHVwZSBvbiBjb3JyZWxhdGlvbklkLiBTa2lwcGluZyB0aGUgaW5saW5lIHN0ZXBcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGF2b2lkcyBhIHF1ZXVlIGhhbmRsZXIgcmFjaW5nIGFnYWluc3Qgb3VyIG93blxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW5saW5lIGV4ZWN1dG9yLlxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBzdGVwIG9mIHBlbmRpbmdTdGVwcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5saW5lU3RlcCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXAuY29ycmVsYXRpb25JZCA9PT0gaW5saW5lU3RlcC5jb3JyZWxhdGlvbklkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRyYWNlQ2FycmllciA9IGF3YWl0IHNlcmlhbGl6ZVRyYWNlQ2FycmllcigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBxdWV1ZU1lc3NhZ2UoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ybGQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0V29ya2Zsb3dRdWV1ZU5hbWUod29ya2Zsb3dOYW1lKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXBJZDogc3RlcC5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcE5hbWU6IHN0ZXAuc3RlcE5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjZUNhcnJpZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXF1ZXN0ZWRBdDogbmV3IERhdGUoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkZW1wb3RlbmN5S2V5OiBzdGVwLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBOb3RoaW5nIHRvIGV4ZWN1dGUgaW5saW5lIOKAlCB3ZSBhbHJlYWR5IHF1ZXVlZCBhbGxcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHBlbmRpbmcgc3RlcHMgYWJvdmUsIGV4aXQgYW5kIGxldCB0aGUgcXVldWUgZHJpdmUuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWlubGluZVN0ZXApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN1c3BlbnNpb25SZXN1bHQudGltZW91dFNlY29uZHMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aW1lb3V0U2Vjb25kczogc3VzcGVuc2lvblJlc3VsdC50aW1lb3V0U2Vjb25kcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRXhlY3V0ZSBpbmxpbmUgc3RlcC4gUGF1c2UgdGhlIHJlcGxheSBidWRnZXRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGZvciB0aGUgZHVyYXRpb24gb2YgdGhlIHN0ZXAgYm9keSDigJQgc3RlcFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZHVyYXRpb24gaXMgYm91bmRlZCBieSB0aGUgcGxhdGZvcm0ncyBmdW5jdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbWF4RHVyYXRpb24sIG5vdCBieSB0aGUgcmVwbGF5IHRpbWVvdXQuIFdpdGhvdXRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoaXMgdGhlIHJlcGxheS1idWRnZXQgY2hlY2sgYXQgdGhlIHRvcCBvZiB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5leHQgbG9vcCBpdGVyYXRpb24gd291bGQgKGluY29ycmVjdGx5KSBjaGFyZ2VcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBzdGVwIGJvZHkgYWdhaW5zdCB0aGUgYnVkZ2V0LlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVwbGF5QnVkZ2V0LnBhdXNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgc3RlcFJlc3VsdDogQXdhaXRlZDxSZXR1cm5UeXBlPHR5cGVvZiBleGVjdXRlU3RlcD4+O1xuICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcFJlc3VsdCA9IGF3YWl0IGV4ZWN1dGVTdGVwKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JsZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd0RlcGxveW1lbnRJZDogd29ya2Zsb3dSdW4uZGVwbG95bWVudElkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93TmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZmxvd1N0YXJ0ZWRBdCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGVwSWQ6IGlubGluZVN0ZXAuY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGVwTmFtZTogaW5saW5lU3RlcC5zdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICByZXBsYXlCdWRnZXQucmVzdW1lKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGVwUmVzdWx0LnR5cGUgPT09ICdyZXRyeScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU3RlcCBuZWVkcyByZXRyeSDigJQgcXVldWUgc2VsZiB3aXRoIHN0ZXBJZCBmb3IgcmV0cnlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdHJhY2VDYXJyaWVyID0gYXdhaXQgc2VyaWFsaXplVHJhY2VDYXJyaWVyKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHF1ZXVlTWVzc2FnZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JsZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRXb3JrZmxvd1F1ZXVlTmFtZSh3b3JrZmxvd05hbWUpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcElkOiBpbmxpbmVTdGVwLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGVwTmFtZTogaW5saW5lU3RlcC5zdGVwTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNlQ2FycmllcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVlc3RlZEF0OiBuZXcgRGF0ZSgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsYXlTZWNvbmRzOiBzdGVwUmVzdWx0LnRpbWVvdXRTZWNvbmRzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhlcmUgYXJlIGFsc28gd2FpdHMsIHJldHVybiB0aGVpciB0aW1lb3V0XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdXNwZW5zaW9uUmVzdWx0LnRpbWVvdXRTZWNvbmRzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGltZW91dFNlY29uZHM6IHN1c3BlbnNpb25SZXN1bHQudGltZW91dFNlY29uZHMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGVwUmVzdWx0LnR5cGUgPT09ICd0aHJvdHRsZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGltZW91dFNlY29uZHM6IHN0ZXBSZXN1bHQudGltZW91dFNlY29uZHMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFN0ZXAgY29tcGxldGVkIG9yIGZhaWxlZCDigJQgbG9vcCBiYWNrIHRvIHJlcGxheVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gKGdvbmUvc2tpcHBlZCBhbHNvIGxvb3AgYmFjayBzaW5jZSB0aGUgd29ya2Zsb3dcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdpbGwgc2VlIHRoZSBjb21wbGV0ZWQvZmFpbGVkIGV2ZW50IG9uIHJlcGxheSlcblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhlIHN0ZXAgaGFkIHBlbmRpbmcgYmFja2dyb3VuZCBvcHMgKGUuZy4sIHN0cmVhbVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gd3JpdGVzIHRvIFMzKSwgYnJlYWsgdGhlIGxvb3AgYW5kIHJldHVybiBzbyB3YWl0VW50aWxcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNhbiBmbHVzaCB0aGVtLiBUaGlzIG1hdGNoZXMgVjEgYmVoYXZpb3Igd2hlcmUgZWFjaFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc3RlcCByYW4gaW4gYSBzZXBhcmF0ZSBmdW5jdGlvbiBpbnZvY2F0aW9uLiBXaXRob3V0XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGlzLCB0aGUgaW5saW5lIGxvb3AgY29udGludWVzIGFuZCB0aGUgc3RyZWFtIGRhdGFcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG1heSBub3QgcmVhY2ggUzMgYmVmb3JlIHRoZSB0ZXN0IHRyaWVzIHRvIHJlYWQgaXQuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXBSZXN1bHQudHlwZSA9PT0gJ2NvbXBsZXRlZCcgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3RlcFJlc3VsdC5oYXNQZW5kaW5nT3BzXG4gICAgICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5kZWJ1ZyhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQnJlYWtpbmcgbG9vcDogc3RlcCBoYXMgcGVuZGluZyBvcHMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9vcEl0ZXJhdGlvbixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXBOYW1lOiBpbmxpbmVTdGVwLnN0ZXBOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgcXVldWVNZXNzYWdlKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmxkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldFdvcmtmbG93UXVldWVOYW1lKHdvcmtmbG93TmFtZSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjZUNhcnJpZXI6IGF3YWl0IHNlcmlhbGl6ZVRyYWNlQ2FycmllcigpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWVzdGVkQXQ6IG5ldyBEYXRlKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc3VzcGVuc2lvblJlc3VsdC50aW1lb3V0U2Vjb25kcyAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHBlbmRpbmdTdGVwcy5sZW5ndGggPT09IDFcbiAgICAgICAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBPbmx5IDEgc3RlcCBhbmQgdGhlcmUncyBhbHNvIHdhaXRzL2hvb2tzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBzdGVwIGlzIGRvbmUsIGJ1dCB3ZSBuZWVkIHRoZSB3YWl0IHRpbWVvdXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTG9vcCBiYWNrIHRvIHJlcGxheSB3aGljaCB3aWxsIHJlLWV2YWx1YXRlXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFVzZXIgY29kZSBlcnJvciBmcm9tIHJ1bldvcmtmbG93IOKAlCBjcmVhdGUgcnVuX2ZhaWxlZC5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnIgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBzcGFuPy5yZWNvcmRFeGNlcHRpb24/LihlcnIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBub3JtYWxpemVkRXJyb3IgPVxuICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBub3JtYWxpemVVbmtub3duRXJyb3IoZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yTmFtZSA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIG5vcm1hbGl6ZWRFcnJvci5uYW1lIHx8IGdldEVycm9yTmFtZShlcnIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID0gbm9ybWFsaXplZEVycm9yLm1lc3NhZ2U7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgZXJyb3JTdGFjayA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIG5vcm1hbGl6ZWRFcnJvci5zdGFjayB8fCBnZXRFcnJvclN0YWNrKGVycik7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvclN0YWNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhcnNlZE5hbWUgPSBwYXJzZVdvcmtmbG93TmFtZSh3b3JrZmxvd05hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmaWxlbmFtZSA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyc2VkTmFtZT8ubW9kdWxlU3BlY2lmaWVyIHx8IHdvcmtmbG93TmFtZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JTdGFjayA9IHJlbWFwRXJyb3JTdGFjayhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvclN0YWNrLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVuYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93Q29kZVxuICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBDbGFzc2lmeSB0aGUgZXJyb3I6IFdvcmtmbG93UnVudGltZUVycm9yIGluZGljYXRlc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYW4gU0RLL3J1bnRpbWUgaXNzdWUsIGFuZCBzZWxlY3RlZCBzdWJjbGFzc2VzIHVzZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbW9yZSBzcGVjaWZpYyBjb2RlcyBmb3IgYmFja2VuZCB0cmFja2luZy5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yQ29kZSA9IGNsYXNzaWZ5UnVuRXJyb3IoZXJyKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5lcnJvcignRXJyb3Igd2hpbGUgcnVubmluZyB3b3JrZmxvdycsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ29kZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvclN0YWNrLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFwcGx5IHRoZSBzb3VyY2UtbWFwLXJlbWFwcGVkIHN0YWNrIHRvIHRoZSB0aHJvd25cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHZhbHVlIHNvIHRoYXQgdGhlIHNlcmlhbGl6ZWQgZXJyb3IgcHJlc2VydmVzIGl0XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBmb3IgY29uc3VtZXJzLiBgdHlwZXMuaXNOYXRpdmVFcnJvcigpYCBpcyB1c2VkXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpbnN0ZWFkIG9mIGBlcnIgaW5zdGFuY2VvZiBFcnJvcmAgYmVjYXVzZSB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdvcmtmbG93IHJ1bnMgaW4gYSBzZXBhcmF0ZSBWTSByZWFsbSDigJQgaXRzIEVycm9yXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjbGFzcyBpcyBkaXN0aW5jdCBmcm9tIHRoZSBob3N0J3MsIHNvIGBpbnN0YW5jZW9mXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBFcnJvcmAgaXMgYGZhbHNlYCBmb3IgVk0tdGhyb3duIGVycm9ycy4gVGhlIFY4XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0eXBlIHRhZyB3b3JrcyBhY3Jvc3MgcmVhbG1zLlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVzLmlzTmF0aXZlRXJyb3IoZXJyKSAmJiBlcnJvclN0YWNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIChlcnIgYXMgRXJyb3IpLnN0YWNrID0gZXJyb3JTdGFjaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRmFpbCB0aGUgd29ya2Zsb3cgcnVuIHZpYSBldmVudCAoZXZlbnQtc291cmNlZCkuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBTZXJpYWxpemUgdGhlIG9yaWdpbmFsIHRocm93biB2YWx1ZSBzbyBpdHMgZnVsbFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdHlwZSBpZGVudGl0eSBhbmQgY3VzdG9tIHByb3BlcnRpZXMgcm91bmQtdHJpcFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhyb3VnaCB0aGUgZXZlbnQgbG9nLlxuICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgd29ybGQuZXZlbnRzLmNyZWF0ZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudFR5cGU6ICdydW5fZmFpbGVkJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvcjogYXdhaXQgZGVoeWRyYXRlUnVuRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuY3J5cHRpb25LZXlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JDb2RlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsgcmVxdWVzdElkIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGZhaWxFcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZmFpbEVycikgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBSdW5FeHBpcmVkRXJyb3IuaXMoZmFpbEVycilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ1RyaWVkIGZhaWxpbmcgd29ya2Zsb3cgcnVuLCBidXQgcnVuIGhhcyBhbHJlYWR5IGZpbmlzaGVkLicsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBmYWlsRXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzV29ybGRDb250cmFjdEVycm9yKGZhaWxFcnIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5lcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdGYXRhbCB3b3JsZCBjb250cmFjdCBlcnJvciB3aGlsZSByZWNvcmRpbmcgd29ya2Zsb3cgZmFpbHVyZScsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckNvZGU6IFJVTl9FUlJPUl9DT0RFUy5XT1JMRF9DT05UUkFDVF9FUlJPUixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3I6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFpbEVyciBpbnN0YW5jZW9mIEVycm9yXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IGZhaWxFcnIubWVzc2FnZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiBTdHJpbmcoZmFpbEVyciksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgZmFpbEVycjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd1J1blN0YXR1cygnZmFpbGVkJyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5Xb3JrZmxvd0Vycm9yQ29kZShlcnJvckNvZGUpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dFcnJvck5hbWUoZXJyb3JOYW1lKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uQXR0cmlidXRlLldvcmtmbG93RXJyb3JNZXNzYWdlKGVycm9yTWVzc2FnZSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC4uLkF0dHJpYnV0ZS5FcnJvclR5cGUoZXJyb3JOYW1lKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfSAvLyBFbmQgd2hpbGUgbG9vcFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgKTsgLy8gRW5kIHRyYWNlXG4gICAgICAgICAgICB9XG4gICAgICAgICAgKTsgLy8gRW5kIHdpdGhXb3JrZmxvd0JhZ2dhZ2VcbiAgICAgICAgfSk7IC8vIEVuZCB3aXRoVHJhY2VDb250ZXh0XG4gICAgICB9XG4gICAgKTtcblxuICBsZXQgY2FjaGVkSGFuZGxlcjogKChyZXE6IFJlcXVlc3QpID0+IFByb21pc2U8UmVzcG9uc2U+KSB8IHVuZGVmaW5lZDtcbiAgcmV0dXJuIHdpdGhIZWFsdGhDaGVjayhhc3luYyAocmVxKSA9PiB7XG4gICAgaWYgKCFjYWNoZWRIYW5kbGVyKSB7XG4gICAgICBjYWNoZWRIYW5kbGVyID0gaGFuZGxlcihhd2FpdCBnZXRXb3JsZEhhbmRsZXJzKCkpO1xuICAgIH1cbiAgICByZXR1cm4gY2FjaGVkSGFuZGxlcihyZXEpO1xuICB9KTtcbn1cbiJdfQ==