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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (317) hide show
  1. package/README.md +5 -0
  2. package/dist/attribute-changes.d.ts +5 -0
  3. package/dist/attribute-changes.d.ts.map +1 -0
  4. package/dist/attribute-changes.js +25 -0
  5. package/dist/capabilities.d.ts +35 -2
  6. package/dist/capabilities.d.ts.map +1 -1
  7. package/dist/capabilities.js +74 -5
  8. package/dist/capture-stack.d.ts +1 -1
  9. package/dist/capture-stack.js +2 -2
  10. package/dist/class-serialization.d.ts +32 -0
  11. package/dist/class-serialization.d.ts.map +1 -1
  12. package/dist/class-serialization.js +37 -1
  13. package/dist/classify-error.d.ts +19 -3
  14. package/dist/classify-error.d.ts.map +1 -1
  15. package/dist/classify-error.js +98 -6
  16. package/dist/context-violation-error.d.ts +5 -5
  17. package/dist/context-violation-error.d.ts.map +1 -1
  18. package/dist/context-violation-error.js +8 -6
  19. package/dist/create-hook.d.ts +72 -7
  20. package/dist/create-hook.d.ts.map +1 -1
  21. package/dist/create-hook.js +1 -1
  22. package/dist/define-hook.js +2 -2
  23. package/dist/describe-error.d.ts +7 -7
  24. package/dist/describe-error.d.ts.map +1 -1
  25. package/dist/describe-error.js +97 -12
  26. package/dist/encryption.d.ts +38 -4
  27. package/dist/encryption.d.ts.map +1 -1
  28. package/dist/encryption.js +96 -14
  29. package/dist/events-consumer.d.ts +297 -0
  30. package/dist/events-consumer.d.ts.map +1 -1
  31. package/dist/events-consumer.js +673 -42
  32. package/dist/flushable-stream.d.ts +97 -1
  33. package/dist/flushable-stream.d.ts.map +1 -1
  34. package/dist/flushable-stream.js +291 -11
  35. package/dist/global.d.ts +36 -2
  36. package/dist/global.d.ts.map +1 -1
  37. package/dist/global.js +21 -6
  38. package/dist/index.d.ts +2 -1
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +3 -2
  41. package/dist/log-format.d.ts +2 -2
  42. package/dist/log-format.js +19 -12
  43. package/dist/logger.d.ts +1 -0
  44. package/dist/logger.d.ts.map +1 -1
  45. package/dist/logger.js +10 -6
  46. package/dist/private.d.ts +226 -9
  47. package/dist/private.d.ts.map +1 -1
  48. package/dist/private.js +626 -7
  49. package/dist/replay-divergence.d.ts +25 -0
  50. package/dist/replay-divergence.d.ts.map +1 -0
  51. package/dist/replay-divergence.js +61 -0
  52. package/dist/replay-payload-cache.d.ts +64 -0
  53. package/dist/replay-payload-cache.d.ts.map +1 -0
  54. package/dist/replay-payload-cache.js +158 -0
  55. package/dist/runtime/compute-instance.d.ts +13 -0
  56. package/dist/runtime/compute-instance.d.ts.map +1 -0
  57. package/dist/runtime/compute-instance.js +14 -0
  58. package/dist/runtime/constants.d.ts +315 -0
  59. package/dist/runtime/constants.d.ts.map +1 -1
  60. package/dist/runtime/constants.js +502 -16
  61. package/dist/runtime/count-step-started-events.d.ts +52 -0
  62. package/dist/runtime/count-step-started-events.d.ts.map +1 -0
  63. package/dist/runtime/count-step-started-events.js +72 -0
  64. package/dist/runtime/deployment-guard.d.ts +99 -0
  65. package/dist/runtime/deployment-guard.d.ts.map +1 -0
  66. package/dist/runtime/deployment-guard.js +154 -0
  67. package/dist/runtime/get-port-lazy.d.ts +15 -0
  68. package/dist/runtime/get-port-lazy.d.ts.map +1 -1
  69. package/dist/runtime/get-port-lazy.js +75 -6
  70. package/dist/runtime/get-world-lazy.d.ts +5 -14
  71. package/dist/runtime/get-world-lazy.d.ts.map +1 -1
  72. package/dist/runtime/get-world-lazy.js +19 -29
  73. package/dist/runtime/helpers.d.ts +415 -29
  74. package/dist/runtime/helpers.d.ts.map +1 -1
  75. package/dist/runtime/helpers.js +686 -57
  76. package/dist/runtime/quickjs-assets.generated.d.ts +14 -0
  77. package/dist/runtime/quickjs-assets.generated.d.ts.map +1 -0
  78. package/dist/runtime/quickjs-assets.generated.js +30 -0
  79. package/dist/runtime/quickjs-entrypoint.d.ts +158 -0
  80. package/dist/runtime/quickjs-entrypoint.d.ts.map +1 -0
  81. package/dist/runtime/quickjs-entrypoint.js +1863 -0
  82. package/dist/runtime/quickjs-log-view.d.ts +129 -0
  83. package/dist/runtime/quickjs-log-view.d.ts.map +1 -0
  84. package/dist/runtime/quickjs-log-view.js +229 -0
  85. package/dist/runtime/quickjs-runtime.d.ts +244 -0
  86. package/dist/runtime/quickjs-runtime.d.ts.map +1 -0
  87. package/dist/runtime/quickjs-runtime.js +2427 -0
  88. package/dist/runtime/quickjs-serde.d.ts +107 -0
  89. package/dist/runtime/quickjs-serde.d.ts.map +1 -0
  90. package/dist/runtime/quickjs-serde.js +2159 -0
  91. package/dist/runtime/replay-budget.d.ts +97 -0
  92. package/dist/runtime/replay-budget.d.ts.map +1 -0
  93. package/dist/runtime/replay-budget.js +139 -0
  94. package/dist/runtime/replay-recovery-reporter.d.ts +36 -0
  95. package/dist/runtime/replay-recovery-reporter.d.ts.map +1 -0
  96. package/dist/runtime/replay-recovery-reporter.js +64 -0
  97. package/dist/runtime/resume-hook.d.ts +91 -8
  98. package/dist/runtime/resume-hook.d.ts.map +1 -1
  99. package/dist/runtime/resume-hook.js +512 -89
  100. package/dist/runtime/resume-latency.d.ts +150 -0
  101. package/dist/runtime/resume-latency.d.ts.map +1 -0
  102. package/dist/runtime/resume-latency.js +155 -0
  103. package/dist/runtime/run-id-time.d.ts +19 -0
  104. package/dist/runtime/run-id-time.d.ts.map +1 -0
  105. package/dist/runtime/run-id-time.js +42 -0
  106. package/dist/runtime/run.d.ts +72 -7
  107. package/dist/runtime/run.d.ts.map +1 -1
  108. package/dist/runtime/run.js +280 -53
  109. package/dist/runtime/runs.d.ts +54 -3
  110. package/dist/runtime/runs.d.ts.map +1 -1
  111. package/dist/runtime/runs.js +126 -16
  112. package/dist/runtime/start.d.ts +101 -2
  113. package/dist/runtime/start.d.ts.map +1 -1
  114. package/dist/runtime/start.js +352 -61
  115. package/dist/runtime/step-executor.d.ts +186 -5
  116. package/dist/runtime/step-executor.d.ts.map +1 -1
  117. package/dist/runtime/step-executor.js +768 -130
  118. package/dist/runtime/step-latency.d.ts +220 -0
  119. package/dist/runtime/step-latency.d.ts.map +1 -0
  120. package/dist/runtime/step-latency.js +215 -0
  121. package/dist/runtime/step-ownership.d.ts +72 -0
  122. package/dist/runtime/step-ownership.d.ts.map +1 -0
  123. package/dist/runtime/step-ownership.js +114 -0
  124. package/dist/runtime/step-single-flight.d.ts +12 -0
  125. package/dist/runtime/step-single-flight.d.ts.map +1 -0
  126. package/dist/runtime/step-single-flight.js +75 -0
  127. package/dist/runtime/suspension-handler.d.ts +247 -7
  128. package/dist/runtime/suspension-handler.d.ts.map +1 -1
  129. package/dist/runtime/suspension-handler.js +1304 -125
  130. package/dist/runtime/unserializable-step.d.ts +34 -0
  131. package/dist/runtime/unserializable-step.d.ts.map +1 -0
  132. package/dist/runtime/unserializable-step.js +52 -0
  133. package/dist/runtime/vm-mode.d.ts +44 -0
  134. package/dist/runtime/vm-mode.d.ts.map +1 -0
  135. package/dist/runtime/vm-mode.js +62 -0
  136. package/dist/runtime/vm-serde-bundle.generated.d.ts +14 -0
  137. package/dist/runtime/vm-serde-bundle.generated.d.ts.map +1 -0
  138. package/dist/runtime/vm-serde-bundle.generated.js +16 -0
  139. package/dist/runtime/wait-continuation.d.ts +106 -0
  140. package/dist/runtime/wait-continuation.d.ts.map +1 -0
  141. package/dist/runtime/wait-continuation.js +136 -0
  142. package/dist/runtime/wait-until.d.ts +18 -0
  143. package/dist/runtime/wait-until.d.ts.map +1 -0
  144. package/dist/runtime/wait-until.js +42 -0
  145. package/dist/runtime/world-compatibility.d.ts +32 -0
  146. package/dist/runtime/world-compatibility.d.ts.map +1 -0
  147. package/dist/runtime/world-compatibility.js +44 -0
  148. package/dist/runtime/world-init.d.ts +17 -42
  149. package/dist/runtime/world-init.d.ts.map +1 -1
  150. package/dist/runtime/world-init.js +18 -43
  151. package/dist/runtime/world.d.ts +14 -2
  152. package/dist/runtime/world.d.ts.map +1 -1
  153. package/dist/runtime/world.js +75 -19
  154. package/dist/runtime.d.ts +10 -6
  155. package/dist/runtime.d.ts.map +1 -1
  156. package/dist/runtime.js +3911 -489
  157. package/dist/sealed-box.d.ts +167 -0
  158. package/dist/sealed-box.d.ts.map +1 -0
  159. package/dist/sealed-box.js +571 -0
  160. package/dist/serialization/client.d.ts +3 -3
  161. package/dist/serialization/client.d.ts.map +1 -1
  162. package/dist/serialization/client.js +8 -4
  163. package/dist/serialization/codec-devalue-vm.d.ts +16 -0
  164. package/dist/serialization/codec-devalue-vm.d.ts.map +1 -0
  165. package/dist/serialization/codec-devalue-vm.js +148 -0
  166. package/dist/serialization/codec-devalue.d.ts +1 -1
  167. package/dist/serialization/codec-devalue.d.ts.map +1 -1
  168. package/dist/serialization/codec-devalue.js +24 -6
  169. package/dist/serialization/codec.d.ts +37 -2
  170. package/dist/serialization/codec.d.ts.map +1 -1
  171. package/dist/serialization/codec.js +2 -2
  172. package/dist/serialization/compression.d.ts +105 -0
  173. package/dist/serialization/compression.d.ts.map +1 -0
  174. package/dist/serialization/compression.js +261 -0
  175. package/dist/serialization/encryption.d.ts +119 -17
  176. package/dist/serialization/encryption.d.ts.map +1 -1
  177. package/dist/serialization/encryption.js +152 -17
  178. package/dist/serialization/errors.d.ts +13 -0
  179. package/dist/serialization/errors.d.ts.map +1 -1
  180. package/dist/serialization/errors.js +20 -2
  181. package/dist/serialization/format.d.ts +6 -6
  182. package/dist/serialization/format.js +7 -7
  183. package/dist/serialization/hardened.d.ts +156 -0
  184. package/dist/serialization/hardened.d.ts.map +1 -0
  185. package/dist/serialization/hardened.js +538 -0
  186. package/dist/serialization/index.d.ts +10 -8
  187. package/dist/serialization/index.d.ts.map +1 -1
  188. package/dist/serialization/index.js +10 -8
  189. package/dist/serialization/reducers/class-vm.d.ts +20 -0
  190. package/dist/serialization/reducers/class-vm.d.ts.map +1 -0
  191. package/dist/serialization/reducers/class-vm.js +77 -0
  192. package/dist/serialization/reducers/class.d.ts.map +1 -1
  193. package/dist/serialization/reducers/class.js +11 -6
  194. package/dist/serialization/reducers/common-vm.d.ts +15 -0
  195. package/dist/serialization/reducers/common-vm.d.ts.map +1 -0
  196. package/dist/serialization/reducers/common-vm.js +616 -0
  197. package/dist/serialization/reducers/common.d.ts +1 -1
  198. package/dist/serialization/reducers/common.d.ts.map +1 -1
  199. package/dist/serialization/reducers/common.js +202 -62
  200. package/dist/serialization/reducers/step-function-vm.d.ts +44 -0
  201. package/dist/serialization/reducers/step-function-vm.d.ts.map +1 -0
  202. package/dist/serialization/reducers/step-function-vm.js +97 -0
  203. package/dist/serialization/reducers/step-function.d.ts.map +1 -1
  204. package/dist/serialization/reducers/step-function.js +25 -9
  205. package/dist/serialization/step.d.ts +4 -4
  206. package/dist/serialization/step.d.ts.map +1 -1
  207. package/dist/serialization/step.js +9 -5
  208. package/dist/serialization/types.d.ts +80 -1
  209. package/dist/serialization/types.d.ts.map +1 -1
  210. package/dist/serialization/types.js +15 -1
  211. package/dist/serialization/workflow-vm.d.ts +29 -0
  212. package/dist/serialization/workflow-vm.d.ts.map +1 -0
  213. package/dist/serialization/workflow-vm.js +74 -0
  214. package/dist/serialization-format.d.ts +64 -8
  215. package/dist/serialization-format.d.ts.map +1 -1
  216. package/dist/serialization-format.js +225 -73
  217. package/dist/serialization.d.ts +262 -34
  218. package/dist/serialization.d.ts.map +1 -1
  219. package/dist/serialization.js +1885 -277
  220. package/dist/set-attributes.d.ts +13 -0
  221. package/dist/set-attributes.d.ts.map +1 -0
  222. package/dist/set-attributes.js +60 -0
  223. package/dist/source-map.d.ts +25 -0
  224. package/dist/source-map.d.ts.map +1 -1
  225. package/dist/source-map.js +154 -10
  226. package/dist/step/context-storage.d.ts +63 -2
  227. package/dist/step/context-storage.d.ts.map +1 -1
  228. package/dist/step/context-storage.js +7 -5
  229. package/dist/step/writable-stream.d.ts +3 -3
  230. package/dist/step/writable-stream.d.ts.map +1 -1
  231. package/dist/step/writable-stream.js +80 -13
  232. package/dist/step.d.ts.map +1 -1
  233. package/dist/step.js +148 -27
  234. package/dist/symbols.d.ts +50 -0
  235. package/dist/symbols.d.ts.map +1 -1
  236. package/dist/symbols.js +51 -1
  237. package/dist/telemetry/semantic-conventions.d.ts +433 -2
  238. package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
  239. package/dist/telemetry/semantic-conventions.js +319 -3
  240. package/dist/telemetry.d.ts +91 -0
  241. package/dist/telemetry.d.ts.map +1 -1
  242. package/dist/telemetry.js +244 -17
  243. package/dist/test-support/orchestrator-context.d.ts +25 -0
  244. package/dist/test-support/orchestrator-context.d.ts.map +1 -0
  245. package/dist/test-support/orchestrator-context.js +107 -0
  246. package/dist/types.d.ts +6 -0
  247. package/dist/types.d.ts.map +1 -1
  248. package/dist/types.js +23 -1
  249. package/dist/util.d.ts +0 -5
  250. package/dist/util.d.ts.map +1 -1
  251. package/dist/util.js +1 -15
  252. package/dist/version.d.ts +1 -1
  253. package/dist/version.d.ts.map +1 -1
  254. package/dist/version.js +2 -2
  255. package/dist/vm/index.d.ts.map +1 -1
  256. package/dist/vm/index.js +84 -14
  257. package/dist/vm/script-cache.d.ts +26 -0
  258. package/dist/vm/script-cache.d.ts.map +1 -0
  259. package/dist/vm/script-cache.js +131 -0
  260. package/dist/vm/uint8array-base64.js +1 -1
  261. package/dist/workflow/abort-controller.d.ts +2 -2
  262. package/dist/workflow/abort-controller.d.ts.map +1 -1
  263. package/dist/workflow/abort-controller.js +88 -21
  264. package/dist/workflow/attribute-dispatcher.d.ts +6 -0
  265. package/dist/workflow/attribute-dispatcher.d.ts.map +1 -0
  266. package/dist/workflow/attribute-dispatcher.js +45 -0
  267. package/dist/workflow/create-hook.d.ts.map +1 -1
  268. package/dist/workflow/create-hook.js +24 -3
  269. package/dist/workflow/get-workflow-metadata.js +2 -2
  270. package/dist/workflow/hook.d.ts.map +1 -1
  271. package/dist/workflow/hook.js +304 -47
  272. package/dist/workflow/index.d.ts +1 -0
  273. package/dist/workflow/index.d.ts.map +1 -1
  274. package/dist/workflow/index.js +2 -1
  275. package/dist/workflow/set-attributes.d.ts +68 -0
  276. package/dist/workflow/set-attributes.d.ts.map +1 -0
  277. package/dist/workflow/set-attributes.js +60 -0
  278. package/dist/workflow/sleep.d.ts.map +1 -1
  279. package/dist/workflow/sleep.js +58 -12
  280. package/dist/workflow/world-init-stub.d.ts +3 -3
  281. package/dist/workflow/world-init-stub.js +4 -4
  282. package/dist/workflow.d.ts +95 -3
  283. package/dist/workflow.d.ts.map +1 -1
  284. package/dist/workflow.js +900 -561
  285. package/docs/api-reference/create-hook.mdx +89 -10
  286. package/docs/api-reference/create-webhook.mdx +16 -15
  287. package/docs/api-reference/define-hook.mdx +35 -33
  288. package/docs/api-reference/fatal-error.mdx +30 -8
  289. package/docs/api-reference/fetch.mdx +14 -10
  290. package/docs/api-reference/get-step-metadata.mdx +2 -2
  291. package/docs/api-reference/get-workflow-metadata.mdx +3 -3
  292. package/docs/api-reference/get-writable.mdx +7 -7
  293. package/docs/api-reference/index.mdx +4 -1
  294. package/docs/api-reference/retryable-error.mdx +1 -1
  295. package/docs/api-reference/set-attributes.mdx +61 -0
  296. package/docs/api-reference/sleep.mdx +4 -4
  297. package/docs/foundations/cancellation.mdx +31 -32
  298. package/docs/foundations/errors-and-retries.mdx +42 -11
  299. package/docs/foundations/hooks.mdx +64 -35
  300. package/docs/foundations/idempotency.mdx +244 -12
  301. package/docs/foundations/index.mdx +1 -23
  302. package/docs/foundations/meta.json +2 -1
  303. package/docs/foundations/serialization.mdx +21 -22
  304. package/docs/foundations/starting-workflows.mdx +106 -30
  305. package/docs/foundations/streaming.mdx +108 -60
  306. package/docs/foundations/versioning.mdx +263 -0
  307. package/docs/foundations/workflows-and-steps.mdx +9 -9
  308. package/docs/how-it-works/cancellation.mdx +63 -63
  309. package/docs/how-it-works/code-transform.mdx +83 -67
  310. package/docs/how-it-works/encryption.mdx +30 -26
  311. package/docs/how-it-works/event-sourcing.mdx +125 -34
  312. package/docs/how-it-works/framework-integrations.mdx +96 -337
  313. package/docs/how-it-works/understanding-directives.mdx +22 -22
  314. package/package.json +24 -15
  315. package/dist/runtime/step-handler.d.ts +0 -2
  316. package/dist/runtime/step-handler.d.ts.map +0 -1
  317. package/dist/runtime/step-handler.js +0 -776
package/dist/private.js CHANGED
@@ -1,6 +1,9 @@
1
1
  /**
2
2
  * Utils used by the bundler when transforming code
3
3
  */
4
+ import { WorkflowRuntimeError } from '@workflow/errors';
5
+ import { withResolvers } from '@workflow/utils';
6
+ import { WorkflowSuspension } from './global.js';
4
7
  const RegisteredStepsKey = Symbol.for('@workflow/core//registeredSteps');
5
8
  const globalSymbols = globalThis;
6
9
  // biome-ignore lint/suspicious/noAssignInExpressions: /
@@ -85,18 +88,625 @@ export function getStepFunction(stepId) {
85
88
  }
86
89
  return undefined;
87
90
  }
91
+ /**
92
+ * Which earlier kinds each delivery kind defers behind. Chosen so that no kind
93
+ * blocks on a peer it does not need to:
94
+ *
95
+ * - a hook defers behind earlier HOOKS, WAITS and STEPS;
96
+ * - a wait defers behind earlier HOOKS and STEPS (not earlier waits, since a
97
+ * wait never needs to queue behind another wait);
98
+ * - a step defers behind earlier WAITS, HOOKS and STEPS.
99
+ *
100
+ * The step-behind-step edge is not redundant with the serial `promiseQueue`.
101
+ * The queue fixes the order in which step results are HYDRATED, but a step no
102
+ * longer resolves inside its queue slot: it captures the outcome there and
103
+ * resolves from a detached continuation once its barrier clears. Two steps
104
+ * agree on that continuation's ordering only while they defer behind the same
105
+ * set, which holds when they are consumed in the same drain window but not
106
+ * across windows: a step consumed later can miss a wait/hook barrier that an
107
+ * earlier step is still parked on, because the barrier retired in between. The
108
+ * earlier step is then waiting out the macrotask yield below while the later
109
+ * one resolves on microtasks, and overtakes it. See
110
+ * `delivery-barrier-coverage.test.ts`. Deferring behind earlier steps
111
+ * closes that window structurally: the earlier step's barrier is still
112
+ * registered precisely because it has not delivered yet.
113
+ *
114
+ * Every edge points from a later log index to a strictly earlier one, so the
115
+ * wait-for graph can never contain a cycle.
116
+ */
117
+ const DEFER_BEHIND = {
118
+ hook: ['hook', 'wait', 'step'],
119
+ wait: ['hook', 'step'],
120
+ step: ['wait', 'hook', 'step'],
121
+ };
122
+ /**
123
+ * Whether a delivery of `kind` at log index `index` gates on the earlier
124
+ * registry entry `other` (at `otherIndex`).
125
+ *
126
+ * Single source of truth for that question, called by both
127
+ * {@link awaitEarlierDeliveries} (which awaits what it gates on) and
128
+ * {@link computeResolvesOnItsOwn} (which recurses into what it gates on).
129
+ * Those two MUST agree exactly, and the doc block on
130
+ * {@link awaitEarlierDeliveries} stakes deadlock-freedom on it, so the
131
+ * condition lives here rather than being spelled out twice.
132
+ *
133
+ * One deliberate exception: the log-order-draws turnstile in
134
+ * {@link quiesceEarlierCascades} waits on ANY lower armed entry, a strictly
135
+ * wider relation than this one. Why that width cannot deadlock the
136
+ * safety-net dispenser is argued at the turnstile itself.
137
+ */
138
+ function gatesOn(kind, index, otherIndex, other) {
139
+ if (otherIndex >= index || !DEFER_BEHIND[kind].includes(other.kind)) {
140
+ return false;
141
+ }
142
+ // A step skips an UNARMED earlier entry (an unclaimed buffered hook
143
+ // payload). See the asymmetry described on `awaitEarlierDeliveries`. The
144
+ // skip is direct, never transitive: armed entries are still gated on, even
145
+ // when they are themselves parked behind such a payload.
146
+ return !(kind === 'step' && !other.armed);
147
+ }
148
+ /**
149
+ * Whether `entry` will resolve on its own: it is armed, and every earlier
150
+ * delivery it actually gates on ({@link gatesOn}) will likewise resolve on its
151
+ * own.
152
+ *
153
+ * A step does not gate on an unclaimed buffered payload, so such a payload
154
+ * cannot keep it from resolving. A step DOES gate on earlier armed waits and
155
+ * hooks, so one parked behind an unclaimed payload makes the step
156
+ * non-self-resolving in turn. Disagreeing with {@link awaitEarlierDeliveries}
157
+ * here would not be a cosmetic problem: this predicate is what
158
+ * {@link hasParkedCommittedDelivery} uses to decide whether idle is reachable,
159
+ * and an entry reported self-resolving while it is in fact parked behind a
160
+ * payload that only the idle safety net can retire would gate its own
161
+ * retirement.
162
+ *
163
+ * Recursion terminates because every edge points to a strictly smaller index.
164
+ * `memo` keeps the walk linear in registry size, and the registry is not small
165
+ * by construction: `EventsConsumer` drains consecutively consumable events
166
+ * synchronously while barriers only retire on microtask-driven deliveries, so
167
+ * a fan-out of `Promise.race([hook, sleep])` branches accumulates one barrier
168
+ * per branch per kind. The memo MUST be per-call: `armed` mutates between
169
+ * calls as buffered payloads are claimed.
170
+ *
171
+ * The memo is an optimization, not a correctness requirement. It once was one:
172
+ * `awaitEarlierDeliveries` used to run this walk for every earlier entry of a
173
+ * step delivery, with no early exit, which unmemoized is T(n) = Σ T(j),
174
+ * measured at 4.3e8 recursive calls (84s) for 40 alternating armed hook/wait
175
+ * barriers. That call site is gone; a step now tests `armed` directly. The one
176
+ * surviving caller, {@link hasParkedCommittedDelivery}, cannot reach that
177
+ * shape: it returns at the FIRST self-resolving entry, so it only ever
178
+ * advances past entries that are non-self-resolving, and those short-circuit
179
+ * on their first false child. Every entry it evaluates therefore has
180
+ * all-false predecessors and returns after one child, degenerating the walk to
181
+ * a chain (measured: 98 calls unmemoized for the worst 40-barrier shape, 1
182
+ * call for the registry above). Do not restore an exponential claim here
183
+ * without restoring a caller that can produce it.
184
+ */
185
+ function resolvesOnItsOwn(barriers, index, entry, memo) {
186
+ const cached = memo.get(index);
187
+ if (cached !== undefined) {
188
+ return cached;
189
+ }
190
+ const result = computeResolvesOnItsOwn(barriers, index, entry, memo);
191
+ memo.set(index, result);
192
+ return result;
193
+ }
194
+ function computeResolvesOnItsOwn(barriers, index, entry, memo) {
195
+ if (!entry.armed) {
196
+ return false;
197
+ }
198
+ for (const [otherIndex, other] of barriers) {
199
+ if (!gatesOn(entry.kind, index, otherIndex, other)) {
200
+ continue;
201
+ }
202
+ if (!resolvesOnItsOwn(barriers, otherIndex, other, memo)) {
203
+ return false;
204
+ }
205
+ }
206
+ return true;
207
+ }
208
+ /**
209
+ * Awaits, in strict event-log order, every still-registered delivery that is
210
+ * earlier in the log than `eventIndex` and that a delivery of `kind` defers
211
+ * behind (see {@link DEFER_BEHIND}), so that this resolution is handed to the
212
+ * workflow only after all relevant earlier-in-log deliveries have been. This
213
+ * is what keeps a `Promise.race` (or the ULID a follow-up `useStep` draws on
214
+ * a concurrent branch) deterministic and aligned with the committed event
215
+ * log, independent of microtask-hop counts, hydration time, or race-argument
216
+ * order. When this delivery does have to wait, it also yields a macrotask
217
+ * afterwards so the earlier delivery's consumer can run to its own next
218
+ * suspension point first; see the comment at that `await` for why ordering the
219
+ * `resolve()` calls alone is not enough.
220
+ *
221
+ * What counts as "defers behind" is {@link gatesOn}, shared with
222
+ * {@link computeResolvesOnItsOwn} so the two cannot drift.
223
+ *
224
+ * One asymmetry: a STEP result skips any earlier delivery that is UNARMED,
225
+ * i.e. a buffered hook payload no consumer has claimed. Such a payload is
226
+ * delivered only when the workflow next reads the hook, and reaching that read
227
+ * often requires the step result itself (`await stepX()` before the
228
+ * read). Gating the step on it would stall the workflow until the barrier's
229
+ * idle safety net fires, which then releases every delivery queued behind that
230
+ * payload at once, losing exactly the race this ordering exists to protect.
231
+ * Waits and hooks keep gating on unclaimed payloads: for them, waiting for the
232
+ * claim IS the ordering guarantee (a `wait_completed` must not preempt a
233
+ * payload the log ordered first).
234
+ *
235
+ * The skip is direct, never transitive. A step still gates on an earlier ARMED
236
+ * wait or hook, including one that is itself parked behind an unclaimed
237
+ * payload. Skipping those too would invert log order for the commonest shape
238
+ * there is: a workflow that creates a hook it does not read on this branch,
239
+ * races `step` against `sleep`, and has the log say the sleep won. The step
240
+ * would then overtake the wait, both branches would swap the correlation ids
241
+ * they draw next, and replay would diverge. See
242
+ * `step-delivery-ordering.test.ts`. Waiting instead is safe because the
243
+ * payload's own idle safety net retires it and the whole chain then delivers
244
+ * in log order; {@link hasParkedCommittedDelivery} deliberately reports such a
245
+ * step as not self-resolving so that idle stays reachable.
246
+ *
247
+ * "The whole chain then delivers in log order" rests on the PAYLOAD's barrier
248
+ * being retired before that of anything parked behind it. That order is
249
+ * structural: safety-net retirements go through one per-context dispenser that
250
+ * only ever retires the lowest-index entry at delivery idle, and every
251
+ * retirement that wakes a chain flips {@link hasParkedCommittedDelivery} back
252
+ * to true, re-blocking the dispenser until the chain has drained. See
253
+ * {@link ensureBarrierSafetyNet}. (This used to rest on the FIFO of one idle
254
+ * poll per barrier, which held for a single parked segment but decayed to
255
+ * timing noise with several: the release order, and therefore the ULIDs
256
+ * drawn by the woken branches, then depended on how much log the replay had
257
+ * loaded. storm-log-replay.test.ts replays a production log corrupted exactly
258
+ * that way.)
259
+ */
260
+ /**
261
+ * Whether correlation-id draw order is pinned to event-log order. Default ON:
262
+ * only the literal string `WORKFLOW_LOG_ORDER_DRAWS=0` opts out. `=false`,
263
+ * `=off`, and every other value keep it enabled. Read per call so tests can
264
+ * flip it.
265
+ *
266
+ * Off, a delivery that had to defer yields ONE macrotask after its
267
+ * predecessors resolve. This is enough for short consumers, but a woken branch
268
+ * whose path to its next draw crosses more hops (a `Promise.race` resolution, a
269
+ * user-level semaphore, an async-iterator read) can still be overtaken by a
270
+ * later-in-log delivery's shorter cascade, so the run's draw order, including
271
+ * its correlation ids, depends on how much log this replay loaded.
272
+ * On, the yield becomes a fixpoint: the delivery resolves only once every
273
+ * earlier cascade has quiesced, making the draw sequence a pure function of
274
+ * the dense log, stable under prefix extension, and concurrent writers'
275
+ * duplicate creates identical (deduped) instead of colliding.
276
+ */
277
+ function isLogOrderDrawsEnabled() {
278
+ return process.env.WORKFLOW_LOG_ORDER_DRAWS !== '0';
279
+ }
280
+ /**
281
+ * One quiescence turn: lets the entire pending microtask queue drain, then
282
+ * yields to the event loop once. `setImmediate` (check phase) is used where
283
+ * available because Node clamps `setTimeout(0)` to ~1ms while `setImmediate`
284
+ * costs ~20µs. Every branch-deciding delivery pays this turn at least
285
+ * once, so on a sequential replay the clamp is the whole cost. Timers still
286
+ * run between consecutive turns (the loop re-enters the event loop each
287
+ * iteration, passing through the timers phase), so chains parked on the
288
+ * safety-net dispenser's `setTimeout` cadence are not starved.
289
+ */
290
+ function quiescenceTurn(delayMs) {
291
+ if (delayMs === 0 && typeof setImmediate === 'function') {
292
+ return new Promise((resolve) => setImmediate(resolve));
293
+ }
294
+ return new Promise((resolve) => setTimeout(resolve, delayMs));
295
+ }
296
+ /**
297
+ * Waits until the workflow can make no further progress without another
298
+ * delivery: repeated (promise-queue drain + event-loop turn)s until a full
299
+ * turn passes with no new ULID draws and no hydration in flight.
300
+ *
301
+ * Termination: each extra iteration requires a new ULID draw or a hydration
302
+ * started in the previous turn. `mintCount` counts EVERY draw from the run's
303
+ * sequence, including correlation ids and serialization-driven draws (stream
304
+ * ids minted through the `STABLE_ULID` global while dehydrating). This is
305
+ * conservative in the safe direction: serialization draws only extend the
306
+ * wait, and both body progress and the serialization work one cascade can
307
+ * schedule are finite between deliveries, so the fixpoint is reached. The
308
+ * loop holds this delivery's own barrier registered (its `markDelivered` has
309
+ * not run), so `isDeliveryIdle` stays false and no suspension can preempt the
310
+ * cascade being waited out.
311
+ *
312
+ * A rejected `promiseQueue` settles immediately and forever, so looping at
313
+ * the normal cadence on a failed run would degenerate into a busy loop (the
314
+ * same hazard {@link ensureBarrierSafetyNet} documents). Iterations that
315
+ * observe the queue rejected back off to a 50ms tick instead.
316
+ */
317
+ async function quiesceEarlierCascades(ctx, eventIndex) {
318
+ for (;;) {
319
+ const mintsBefore = ctx.mintCount ?? 0;
320
+ const pendingBefore = ctx.pendingDeliveries;
321
+ // Settled or rejected, the queue snapshot only orders us behind work
322
+ // already chained; a rejection is the run failing elsewhere.
323
+ const queueRejected = await ctx.promiseQueue.then(() => false, () => true);
324
+ await quiescenceTurn(queueRejected ? 50 : 0);
325
+ if ((ctx.mintCount ?? 0) !== mintsBefore ||
326
+ pendingBefore !== 0 ||
327
+ ctx.pendingDeliveries !== 0) {
328
+ continue;
329
+ }
330
+ // Quiet is not enough on its own: several delivery chains can be sitting
331
+ // in this loop at once, and letting the first quiet observation resolve
332
+ // would break the tie by timer arrival. This mode removes that arrival-order
333
+ // dependence. A lower-index ARMED barrier is a delivery committed to
334
+ // happening that has not happened yet, so this one keeps waiting. Unarmed
335
+ // entries (buffered payloads nobody has claimed) do not block, exactly as
336
+ // in `gatesOn`: their handover is claim-driven, which is body-position
337
+ // determined and therefore already a function of the prefix.
338
+ //
339
+ // This is deliberately a WIDER waits-for relation than `gatesOn` (which,
340
+ // e.g., excludes wait→wait): under log-order draws EVERY branch-deciding
341
+ // delivery must resolve in log order, kinds included. The width is safe
342
+ // against the dispenser deadlock that `resolvesOnItsOwn` guards, because
343
+ // the one edge the wider relation adds (waiting on an armed entry that
344
+ // gatesOn does not model) always bottoms out at the same unarmed payload:
345
+ // a lower armed WAIT is non-self-resolving only when it is (transitively)
346
+ // parked behind an unclaimed buffered payload, and a wait gates on every
347
+ // lower hook and step directly, so the spinner here also gates on that
348
+ // payload through `gatesOn` and is itself reported non-self-resolving.
349
+ // The dispenser therefore stays unblocked and retires the chain head; see
350
+ // the parked-chain test in delivery-barrier-coverage.test.ts.
351
+ let lowerArmed = false;
352
+ for (const [index, entry] of ctx.pendingDeliveryBarriers ?? []) {
353
+ if (index < eventIndex && entry.armed) {
354
+ lowerArmed = true;
355
+ break;
356
+ }
357
+ }
358
+ if (!lowerArmed) {
359
+ return;
360
+ }
361
+ }
362
+ }
363
+ export async function awaitEarlierDeliveries(ctx, eventIndex, kind) {
364
+ // Defensive: tolerate contexts that predate this field (test harnesses).
365
+ if (eventIndex === undefined || !ctx.pendingDeliveryBarriers) {
366
+ return;
367
+ }
368
+ const barriers = ctx.pendingDeliveryBarriers;
369
+ const earlier = [];
370
+ for (const [index, entry] of barriers) {
371
+ if (!gatesOn(kind, eventIndex, index, entry)) {
372
+ continue;
373
+ }
374
+ earlier.push(entry.released);
375
+ }
376
+ if (earlier.length > 0) {
377
+ await Promise.all(earlier);
378
+ }
379
+ if (isLogOrderDrawsEnabled()) {
380
+ // Unconditional, not just when a barrier was still registered: an earlier
381
+ // delivery's barrier deregisters when its resolve() runs, but the branch
382
+ // it woke may still be hops away from its next draw. A later delivery
383
+ // consumed after that deregistration sees an empty gate set, and without
384
+ // this it would resolve mid-cascade and overtake the draw. This is the exact
385
+ // arrival-order dependence this mode exists to remove. Costs one quiet
386
+ // macrotask turn when nothing is in flight.
387
+ await quiesceEarlierCascades(ctx, eventIndex);
388
+ return;
389
+ }
390
+ if (earlier.length > 0) {
391
+ // An earlier delivery being "delivered" only means its `resolve()` ran.
392
+ // The branch it woke may need an arbitrary number of further microtask
393
+ // hops before it reaches its next `useStep` call and draws a ULID: a
394
+ // `for await` over a hook, for instance, resumes the generator, settles
395
+ // the promise from `next()`, and only then runs the loop body. Resolving
396
+ // this delivery on a microtask would let it overtake that branch and
397
+ // reorder the ULID allocation anyway, turning the guarantee below into a
398
+ // hop-count race that holds only for the shortest consumers.
399
+ //
400
+ // Yielding a macrotask lets the earlier branch's entire microtask chain
401
+ // drain first, whatever its length, so log order survives regardless of
402
+ // how the workflow consumes the earlier delivery. Only deliveries that
403
+ // actually had to defer pay this, so the common single-delivery drain is
404
+ // unaffected.
405
+ await new Promise((resolve) => setTimeout(resolve, 0));
406
+ }
407
+ }
408
+ /**
409
+ * Register a branch-deciding delivery at its event-log index so that later
410
+ * deliveries can be ordered strictly after it. Returns an inert handle when
411
+ * `pendingDeliveryBarriers` is not initialized.
412
+ *
413
+ * Pass `armed: false` for a delivery whose resolution waits on workflow code
414
+ * asking for it (a buffered hook payload); call `arm()` when it does.
415
+ *
416
+ * To guarantee a later delivery gated on this one can never hang when this
417
+ * delivery is abandoned (the workflow took a different branch or is
418
+ * suspending and never observes it), the barrier auto-resolves at idle.
419
+ *
420
+ * INVARIANT required of every call site: a barrier that is ever `armed` must
421
+ * be paired with a delivery chain that runs unconditionally, attached when
422
+ * the event is consumed (waits, step results, waiting-consumer hook payloads,
423
+ * aborts), or by the `claim()` whose invocation is what arms it (buffered
424
+ * hook payloads). The idle check ({@link scheduleWhenIdle}) refuses to
425
+ * observe idle while an armed, self-resolving barrier is undelivered, and the
426
+ * safety net below is itself idle-gated, so an armed barrier with no
427
+ * unconditional chain would livelock every idle check in the run, including
428
+ * its own retirement.
429
+ */
430
+ export function registerDeliveryBarrier(ctx, eventIndex, kind, options = {}) {
431
+ const barriers = ctx.pendingDeliveryBarriers;
432
+ if (!barriers || eventIndex === undefined) {
433
+ return { markDelivered: () => { }, arm: () => { } };
434
+ }
435
+ const install = (armed) => {
436
+ if (barriers.has(eventIndex)) {
437
+ throw new WorkflowRuntimeError(`Delivery barrier already registered at event index ${eventIndex}`);
438
+ }
439
+ const { promise, resolve } = withResolvers();
440
+ const entry = {
441
+ kind,
442
+ released: promise,
443
+ armed,
444
+ retired: false,
445
+ retire: () => {
446
+ if (entry.retired) {
447
+ return;
448
+ }
449
+ entry.retired = true;
450
+ if (barriers.get(eventIndex) === entry) {
451
+ barriers.delete(eventIndex);
452
+ }
453
+ resolve();
454
+ },
455
+ };
456
+ barriers.set(eventIndex, entry);
457
+ // Safety net: if this delivery is never delivered to the workflow (its
458
+ // branch was not taken / the run is suspending, or a buffered hook payload
459
+ // is only claimed after a later delivery the workflow is still waiting
460
+ // on), it is retired at idle so a later delivery gated on it cannot
461
+ // deadlock and the registry cannot leak an entry per abandoned delivery.
462
+ // Retirement goes through the context's single ordered dispenser rather
463
+ // than a per-barrier idle poll. See {@link ensureBarrierSafetyNet} for why
464
+ // the ORDER of these retirements is load-bearing.
465
+ ensureBarrierSafetyNet(ctx);
466
+ return entry;
467
+ };
468
+ let entry = install(options.armed ?? true);
469
+ let deliveredToWorkflow = false;
470
+ return {
471
+ markDelivered: () => {
472
+ if (deliveredToWorkflow) {
473
+ return;
474
+ }
475
+ deliveredToWorkflow = true;
476
+ entry.retire();
477
+ },
478
+ arm: () => {
479
+ if (deliveredToWorkflow) {
480
+ return;
481
+ }
482
+ // The idle safety net may retire an unclaimed buffered hook payload
483
+ // while a retained VM keeps its `claim()` closure alive. If workflow
484
+ // code later claims that payload, replace the settled entry so delivery
485
+ // remains non-idle until the claim reaches the workflow.
486
+ if (entry.retired) {
487
+ entry = install(true);
488
+ return;
489
+ }
490
+ if (barriers.get(eventIndex) !== entry) {
491
+ throw new WorkflowRuntimeError(`Delivery barrier lost ownership of event index ${eventIndex}`);
492
+ }
493
+ entry.armed = true;
494
+ },
495
+ };
496
+ }
497
+ /**
498
+ * Contexts whose barrier safety-net dispenser is currently armed. Module-level
499
+ * so the context interface (constructed literally by many test harnesses)
500
+ * needs no new field; entries drop with the context.
501
+ */
502
+ // per-copy-ok: keyed on the orchestrator context object, and a context is armed
503
+ // and observed by the same copy that created it. Entries can never be looked up
504
+ // from another copy because that copy has no reference to the key.
505
+ const activeBarrierSafetyNets = new WeakSet();
506
+ /**
507
+ * The barrier registry's safety net: ONE idle-gated dispenser per context that
508
+ * retires, at each observation of delivery idle, only the LOWEST-index entry
509
+ * still registered, then yields so the chain it released can run before the
510
+ * next retirement is considered.
511
+ *
512
+ * Why one ordered dispenser and not a poll per barrier (which is what this
513
+ * replaced): the order of safety-net retirements decides the delivery order of
514
+ * every chain parked behind an unclaimed buffered hook payload: a hook the
515
+ * workflow never reads (a fire-and-forget `createHook`) parks every later
516
+ * armed wait/hook behind a barrier that only this net can retire. Per-barrier
517
+ * polls fire in whatever order their re-arm cycles land, and each re-arm
518
+ * attaches to a `promiseQueue` that grows between checks, so with several
519
+ * parked segments the release order decays to timing noise. Draws (`useStep`
520
+ * correlation ids) then depend on which segment happened to release first:
521
+ * concretely, on how MUCH log the replay loaded, since that decides what is in
522
+ * the registry. That is the mechanism behind slot-mode CORRUPTED_EVENT_LOG on
523
+ * storm-shaped runs (see storm-log-replay.test.ts, built from a production
524
+ * log): two replays of the same run holding different-length prefixes bound
525
+ * the same correlation ordinal to different steps.
526
+ *
527
+ * Retiring lowest-first is not merely tidy, it is the only order that cannot
528
+ * invert the log: every gate points from a higher index to a strictly lower
529
+ * one, so at delivery idle the lowest undelivered entry gates on nothing
530
+ * still registered: it is the head of every parked chain (in practice, the
531
+ * unclaimed payload itself). Releasing it lets the chain above deliver
532
+ * through the ordinary barrier order; anything the release wakes flips
533
+ * {@link hasParkedCommittedDelivery} back to true, which re-blocks this
534
+ * dispenser until the chain has fully drained. A higher entry must never be
535
+ * retired while a lower one is registered, which is exactly the inversion
536
+ * described on {@link awaitEarlierDeliveries}.
537
+ *
538
+ * The dispenser goes dormant when the registry empties and is re-armed by the
539
+ * next registration, so an idle context holds no live timer.
540
+ */
541
+ function ensureBarrierSafetyNet(ctx) {
542
+ const barriers = ctx.pendingDeliveryBarriers;
543
+ if (!barriers || activeBarrierSafetyNets.has(ctx)) {
544
+ return;
545
+ }
546
+ activeBarrierSafetyNets.add(ctx);
547
+ const rearm = () => {
548
+ setTimeout(check, 0);
549
+ };
550
+ // A rejected promiseQueue settles immediately and forever, so re-arming
551
+ // through it at the normal cadence would degenerate into a busy loop on an
552
+ // abandoned context. Back off instead: correctness only needs the dispenser
553
+ // to still exist, since the registry gates suspension via isDeliveryIdle
554
+ // and a dead dispenser would wedge the run.
555
+ const rearmAfterRejection = () => {
556
+ setTimeout(check, 50);
557
+ };
558
+ const check = () => {
559
+ if (barriers.size === 0) {
560
+ // Dormant. The next registerDeliveryBarrier re-arms.
561
+ activeBarrierSafetyNets.delete(ctx);
562
+ return;
563
+ }
564
+ if (!canRetireAbandonedBarriers(ctx)) {
565
+ // A delivery is hydrating or committed-but-parked on its deferral; let
566
+ // the queue drain and re-check a tick later (same cadence as
567
+ // scheduleWhenIdle).
568
+ ctx.promiseQueue.then(rearm, rearmAfterRejection);
569
+ return;
570
+ }
571
+ // Idle with entries left: nothing remaining delivers on its own, so
572
+ // release parked chains from the head: lowest index first, one at a
573
+ // time, re-reading idle between retirements. A retirement that wakes a
574
+ // chain flips {@link hasParkedCommittedDelivery} synchronously (it is
575
+ // computed from the registry this loop just mutated), which stops the
576
+ // sweep so the chain delivers before anything above it is released. A
577
+ // retirement that wakes nothing (a stale payload no delivery gates on)
578
+ // keeps the sweep going, so a backlog of those drains in ONE idle
579
+ // observation, since pacing them one per timer tick would hold
580
+ // consumed-but-undelivered events hostage long enough to trip the events
581
+ // consumer's unconsumed-event deadline and fail healthy replays.
582
+ while (barriers.size > 0 && canRetireAbandonedBarriers(ctx)) {
583
+ let lowestIndex;
584
+ let lowestEntry;
585
+ for (const [index, entry] of barriers) {
586
+ if (lowestIndex === undefined || index < lowestIndex) {
587
+ lowestIndex = index;
588
+ lowestEntry = entry;
589
+ }
590
+ }
591
+ lowestEntry?.retire();
592
+ }
593
+ setTimeout(check, 0);
594
+ };
595
+ setTimeout(check, 0);
596
+ }
597
+ /**
598
+ * Whether the safety-net dispenser may retire abandoned barriers right now:
599
+ * no hydration in flight and no committed delivery still working through its
600
+ * detached deferral. This is deliberately WEAKER than {@link isDeliveryIdle}:
601
+ * the dispenser is what empties the registry, so gating it on registry
602
+ * emptiness would gate its own work.
603
+ */
604
+ function canRetireAbandonedBarriers(ctx) {
605
+ return ctx.pendingDeliveries === 0 && !hasParkedCommittedDelivery(ctx);
606
+ }
607
+ /**
608
+ * Whether some registered branch-deciding delivery is going to reach the
609
+ * workflow without any further help (it is armed and not transitively parked
610
+ * behind an unclaimed buffered payload, see {@link resolvesOnItsOwn}) but
611
+ * has not been handed over yet.
612
+ *
613
+ * This is the delivery state `pendingDeliveries` cannot see. That counter
614
+ * covers the hydration window inside a serial `promiseQueue` slot and is
615
+ * released there, while the delivery's `resolve()` runs later, from a
616
+ * detached continuation behind {@link awaitEarlierDeliveries}, including its
617
+ * macrotask yield whenever the delivery had to defer. Replaying a batch of N
618
+ * parallel step results consumed in one drain window leaves N-1 of them
619
+ * parked on that yield with `pendingDeliveries` already at 0. An idle check
620
+ * armed during the same window (a pending `sleep()` arms one on every replay)
621
+ * could then observe "idle" mid-deferral and raise a `WorkflowSuspension`
622
+ * BEFORE the workflow's own continuations ran: a suspension carrying none of
623
+ * the follow-up work the batch was about to create, which the runtime
624
+ * dutifully schedules as nothing, leaving the run dormant until an unrelated
625
+ * timer fires (vercel/workflow#3183).
626
+ *
627
+ * Deliveries that do NOT resolve on their own must be excluded, not for
628
+ * accuracy but for termination: an unclaimed buffered hook payload is retired
629
+ * BY the idle safety net in {@link registerDeliveryBarrier}, so counting it
630
+ * here would gate its own retirement. That reasoning extends to whatever is
631
+ * parked behind such a payload (a wait, and a step gating on that wait) for
632
+ * the same reason: the whole chain moves only once the net fires, and it
633
+ * cannot fire while the chain is counted. Self-resolving deliveries always
634
+ * deliver from their own chains (see the INVARIANT on
635
+ * {@link registerDeliveryBarrier}) and never need that net, so waiting on
636
+ * them is deadlock-free.
637
+ */
638
+ export function hasParkedCommittedDelivery(ctx) {
639
+ const barriers = ctx.pendingDeliveryBarriers;
640
+ if (!barriers || barriers.size === 0) {
641
+ return false;
642
+ }
643
+ // Shared across this call only. See `resolvesOnItsOwn`.
644
+ const selfResolving = new Map();
645
+ for (const [index, entry] of barriers) {
646
+ if (resolvesOnItsOwn(barriers, index, entry, selfResolving)) {
647
+ return true;
648
+ }
649
+ }
650
+ return false;
651
+ }
652
+ /**
653
+ * Whether no data delivery (step result, hook payload) is in flight right now.
654
+ *
655
+ * "In flight" is two distinct windows, each with its own guard:
656
+ * `pendingDeliveries > 0` covers hydration inside the serial queue slots, and
657
+ * {@link hasParkedCommittedDelivery} covers the detached gap between a slot
658
+ * releasing that counter and the delivery's `resolve()` actually running,
659
+ * deliberately outside `pendingDeliveries` (see step.ts), and invisible to it.
660
+ *
661
+ * Anything that decides a replay is over, or that a replay went wrong, has to
662
+ * consult this first: while it is false the workflow VM is mid-reaction, so
663
+ * what it has and has not done yet says nothing about the run. Two callers
664
+ * read it, for the two such decisions: {@link scheduleWhenIdle} for the
665
+ * suspension, and the events consumer's unconsumed-event check for divergence.
666
+ *
667
+ * A non-empty barrier registry counts as in flight, even when every remaining
668
+ * entry is parked behind an unclaimed buffered payload. Those entries only
669
+ * move when the safety-net dispenser retires them (lowest-first, see
670
+ * {@link ensureBarrierSafetyNet}), and the deliveries they release are real
671
+ * workflow reactions: a suspension raised before they run would be computed
672
+ * from a VM that has not seen them, scheduling none of their follow-up work
673
+ * and leaving the run dormant (the vercel/workflow#3183 shape). The dispenser
674
+ * itself is gated on {@link canRetireAbandonedBarriers}, the weaker predicate
675
+ * without the registry term, precisely so it can do the draining that this
676
+ * predicate waits for; registry size strictly decreases at each retirement,
677
+ * so idle is always reached.
678
+ */
679
+ export function isDeliveryIdle(ctx) {
680
+ return (ctx.pendingDeliveries === 0 &&
681
+ (!ctx.pendingDeliveryBarriers || ctx.pendingDeliveryBarriers.size === 0));
682
+ }
88
683
  /**
89
684
  * Schedule a callback to fire only after all pending data deliveries
90
685
  * (step results, hook payloads) and async deserialization have completed.
91
- * Uses a polling loop: setTimeout(0) → check pendingDeliveries
92
- * if > 0, wait for promiseQueue → repeat. This handles the multi-round
93
- * delivery pattern where each hook payload delivery cycle appends new
94
- * async work to the promiseQueue.
686
+ * Uses a polling loop: setTimeout(0) → check pendingDeliveries and the
687
+ * barrier registry → if anything is still in flight, wait for promiseQueue →
688
+ * repeat. This handles the multi-round delivery pattern where each hook
689
+ * payload delivery cycle appends new async work to the promiseQueue. What
690
+ * counts as in flight is {@link isDeliveryIdle}.
691
+ *
692
+ * The initial `setTimeout(0)` macrotask is load-bearing and must NOT be
693
+ * downgraded to a microtask (`queueMicrotask`/`Promise.resolve().then`).
694
+ * `pendingDeliveries` only guards the host-side hydration window; between a
695
+ * delivery's `resolve()` and the workflow VM body running its continuation to
696
+ * register the next subscriber, `pendingDeliveries` is already 0 even though
697
+ * the VM is mid-reaction. Node does not guarantee a microtask scheduled in
698
+ * the host context settles after the cross-VM promise chain (resolve in host
699
+ * → workflow code in VM → subscribe back in host); the macrotask boundary
700
+ * gives that chain time to run, so the suspension does not preempt a sibling
701
+ * delivery still in flight. Empirically, replacing it with `queueMicrotask`
702
+ * breaks hook/sleep `Promise.race` ordering (CorruptedEventLogError).
95
703
  */
96
704
  export function scheduleWhenIdle(ctx, fn) {
97
705
  const check = () => {
98
- if (ctx.pendingDeliveries > 0) {
99
- // Still delivering data wait for queue to drain, then re-check
706
+ if (!isDeliveryIdle(ctx)) {
707
+ // A delivery is still hydrating, or is committed but parked behind its
708
+ // deferral (whose resolve runs on a detached timer, not this queue).
709
+ // Either way: let the queue drain, then re-check a timer tick later.
100
710
  ctx.promiseQueue.then(() => {
101
711
  setTimeout(check, 0);
102
712
  });
@@ -107,4 +717,13 @@ export function scheduleWhenIdle(ctx, fn) {
107
717
  };
108
718
  setTimeout(check, 0);
109
719
  }
110
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJpdmF0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9wcml2YXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBZUgsTUFBTSxrQkFBa0IsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLGlDQUFpQyxDQUFDLENBQUM7QUFFekUsTUFBTSxhQUFhLEdBRWYsVUFBVSxDQUFDO0FBRWYsd0RBQXdEO0FBQ3hELE1BQU0sZUFBZSxHQUFHLENBQUMsYUFBYSxDQUFDLGtCQUFrQixDQUFDLEtBQUssSUFBSSxHQUFHLEVBR25FLENBQUMsQ0FBQztBQUVMLE1BQU0sMkJBQTJCLEdBQUcsSUFBSSxHQUFHLENBQUM7SUFDMUMsaUNBQWlDO0lBQ2pDLHlCQUF5QjtJQUN6Qix5QkFBeUI7Q0FDMUIsQ0FBQyxDQUFDO0FBRUgsU0FBUyx3QkFBd0IsQ0FBQyxNQUFjO0lBQzlDLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDakMsSUFBSSxLQUFLLENBQUMsTUFBTSxLQUFLLENBQUMsSUFBSSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssTUFBTSxFQUFFLENBQUM7UUFDOUMsT0FBTyxFQUFFLENBQUM7SUFDWixDQUFDO0lBRUQsTUFBTSxVQUFVLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzVCLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN4QixNQUFNLGlCQUFpQixHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7SUFFNUMsTUFBTSxRQUFRLEdBQUcsQ0FBQyxlQUF1QixFQUFFLEVBQUU7UUFDM0MsSUFBSSxlQUFlLEtBQUssVUFBVSxFQUFFLENBQUM7WUFDbkMsaUJBQWlCLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQ3pDLENBQUM7SUFDSCxDQUFDLENBQUM7SUFFRixJQUFJLFVBQVUsQ0FBQyxVQUFVLENBQUMsY0FBYyxD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akIsSUFBSSxHQUFHLENBQUMsaUJBQWlCLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDOUIsaUVBQWlFO1lBQ2pFLEdBQUcsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRTtnQkFDekIsVUFBVSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztZQUN2QixDQUFDLENBQUMsQ0FBQztRQUNMLENBQUM7YUFBTSxDQUFDO1lBQ04sRUFBRSxFQUFFLENBQUM7UUFDUCxDQUFDO0lBQ0gsQ0FBQyxDQUFDO0lBQ0YsVUFBVSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztBQUN2QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBVdGlscyB1c2VkIGJ5IHRoZSBidW5kbGVyIHdoZW4gdHJhbnNmb3JtaW5nIGNvZGVcbiAqL1xuXG5pbXBvcnQgdHlwZSB7IENyeXB0b0tleSB9IGZyb20gJy4vZW5jcnlwdGlvbi5qcyc7XG5pbXBvcnQgdHlwZSB7IEV2ZW50c0NvbnN1bWVyIH0gZnJvbSAnLi9ldmVudHMtY29uc3VtZXIuanMnO1xuaW1wb3J0IHR5cGUgeyBRdWV1ZUl0ZW0gfSBmcm9tICcuL2dsb2JhbC5qcyc7XG5pbXBvcnQgdHlwZSB7IFNlcmlhbGl6YWJsZSB9IGZyb20gJy4vc2NoZW1hcy5qcyc7XG5cbmV4cG9ydCB0eXBlIFN0ZXBGdW5jdGlvbjxcbiAgQXJncyBleHRlbmRzIFNlcmlhbGl6YWJsZVtdID0gYW55W10sXG4gIFJlc3VsdCBleHRlbmRzIFNlcmlhbGl6YWJsZSB8IHVua25vd24gPSB1bmtub3duLFxuPiA9ICgoLi4uYXJnczogQXJncykgPT4gUHJvbWlzZTxSZXN1bHQ+KSAmIHtcbiAgbWF4UmV0cmllcz86IG51bWJlcjtcbiAgc3RlcElkPzogc3RyaW5nO1xufTtcblxuY29uc3QgUmVnaXN0ZXJlZFN0ZXBzS2V5ID0gU3ltYm9sLmZvcignQHdvcmtmbG93L2NvcmUvL3JlZ2lzdGVyZWRTdGVwcycpO1xuXG5jb25zdCBnbG9iYWxTeW1ib2xzOiB0eXBlb2YgZ2xvYmFsVGhpcyAmIHtcbiAgW1JlZ2lzdGVyZWRTdGVwc0tleV0/OiBNYXA8c3RyaW5nLCBTdGVwRnVuY3Rpb24+O1xufSA9IGdsb2JhbFRoaXM7XG5cbi8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9Bc3NpZ25JbkV4cHJlc3Npb25zOiAvXG5jb25zdCByZWdpc3RlcmVkU3RlcHMgPSAoZ2xvYmFsU3ltYm9sc1tSZWdpc3RlcmVkU3RlcHNLZXldID8/PSBuZXcgTWFwPFxuICBzdHJpbmcsXG4gIFN0ZXBGdW5jdGlvblxuPigpKTtcblxuY29uc3QgQlVJTFRJTl9SRVNQT05TRV9TVEVQX05BTUVTID0gbmV3IFNldChbXG4gICdfX2J1aWx0aW5fcmVzcG9uc2VfYXJyYXlfYnVmZmVyJyxcbiAgJ19fYnVpbHRpbl9yZXNwb25zZV9qc29uJyxcbiAgJ19fYnVpbHRpbl9yZXNwb25zZV90ZXh0Jyxcbl0pO1xuXG5mdW5jdGlvbiBnZXRTdGVwSWRBbGlhc0NhbmRpZGF0ZXMoc3RlcElkOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gIGNvbnN0IHBhcnRzID0gc3RlcElkLnNwbGl0KCcvLycpO1xuICBpZiAocGFydHMubGVuZ3RoICE9PSAzIHx8IHBhcnRzWzBdICE9PSAnc3RlcCcpIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBjb25zdCBtb2R1bGVQYXRoID0gcGFydHNbMV07XG4gIGNvbnN0IGZuTmFtZSA9IHBhcnRzWzJdO1xuICBjb25zdCBtb2R1bGVQYXRoQWxpYXNlcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4gIGNvbnN0IGFkZEFsaWFzID0gKGFsaWFzTW9kdWxlUGF0aDogc3RyaW5nKSA9PiB7XG4gICAgaWYgKGFsaWFzTW9kdWxlUGF0aCAhPT0gbW9kdWxlUGF0aCkge1xuICAgICAgbW9kdWxlUGF0aEFsaWFzZXMuYWRkKGFsaWFzTW9kdWxlUGF0aCk7XG4gICAgfVxuICB9O1xuXG4gIGlmIChtb2R1bGVQYXRoLnN0YXJ0c1dpdGgoJy4vd29ya2Zsb3dzLycpKSB7XG4gICAgY29uc3Qgd29ya2Zsb3dSZWxhdGl2ZVBhdGggPSBtb2R1bGVQYXRoLnNsaWNlKCcuLycubGVuZ3RoKTtcbiAgICBhZGRBbGlhcyhgLi9leGFtcGxlLyR7d29ya2Zsb3dSZWxhdGl2ZVBhdGh9YCk7XG4gICAgYWRkQWxpYXMoYC4vc3JjLyR7d29ya2Zsb3dSZWxhdGl2ZVBhdGh9YCk7XG4gIH0gZWxzZSBpZiAobW9kdWxlUGF0aC5zdGFydHNXaXRoKCcuL2V4YW1wbGUvd29ya2Zsb3dzLycpKSB7XG4gICAgY29uc3Qgd29ya2Zsb3dSZWxhdGl2ZVBhdGggPSBtb2R1bGVQYXRoLnNsaWNlKCcuL2V4YW1wbGUvJy5sZW5ndGgpO1xuICAgIGFkZEFsaWFzKGAuLyR7d29ya2Zsb3dSZWxhdGl2ZVBhdGh9YCk7XG4gICAgYWRkQWxpYXMoYC4vc3JjLyR7d29ya2Zsb3dSZWxhdGl2ZVBhdGh9YCk7XG4gIH0gZWxzZSBpZiAobW9kdWxlUGF0aC5zdGFydHNXaXRoKCcuL3NyYy93b3JrZmxvd3MvJykpIHtcbiAgICBjb25zdCB3b3JrZmxvd1JlbGF0aXZlUGF0aCA9IG1vZHVsZVBhdGguc2xpY2UoJy4vc3JjLycubGVuZ3RoKTtcbiAgICBhZGRBbGlhcyhgLi8ke3dvcmtmbG93UmVsYXRpdmVQYXRofWApO1xuICAgIGFkZEFsaWFzKGAuL2V4YW1wbGUvJHt3b3JrZmxvd1JlbGF0aXZlUGF0aH1gKTtcbiAgfVxuXG4gIHJldHVybiBBcnJheS5mcm9tKFxuICAgIG1vZHVsZVBhdGhBbGlhc2VzLFxuICAgIChhbGlhc01vZHVsZVBhdGgpID0+IGBzdGVwLy8ke2FsaWFzTW9kdWxlUGF0aH0vLyR7Zm5OYW1lfWBcbiAgKTtcbn1cblxuZnVuY3Rpb24gZ2V0QnVpbHRpblJlc3BvbnNlU3RlcEFsaWFzKHN0ZXBJZDogc3RyaW5nKTogU3RlcEZ1bmN0aW9uIHwgdW5kZWZpbmVkIHtcbiAgaWYgKCFCVUlMVElOX1JFU1BPTlNFX1NURVBfTkFNRVMuaGFzKHN0ZXBJZCkpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgZm9yIChjb25zdCBbcmVnaXN0ZXJlZFN0ZXBJZCwgc3RlcEZuXSBvZiByZWdpc3RlcmVkU3RlcHMuZW50cmllcygpKSB7XG4gICAgaWYgKHJlZ2lzdGVyZWRTdGVwSWQuZW5kc1dpdGgoYC8vJHtzdGVwSWR9YCkpIHtcbiAgICAgIHJldHVybiBzdGVwRm47XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBSZWdpc3RlciBhIHN0ZXAgZnVuY3Rpb24gdG8gYmUgc2VydmVkIGluIHRoZSBzZXJ2ZXIgYnVuZGxlLlxuICogQWxzbyBzZXRzIHRoZSBzdGVwSWQgcHJvcGVydHkgb24gdGhlIGZ1bmN0aW9uIGZvciBzZXJpYWxpemF0aW9uIHN1cHBvcnQuXG4gKlxuICogTm90ZTogVGhlIFNXQyBjb21waWxlciBwbHVnaW4gbm8gbG9uZ2VyIGdlbmVyYXRlcyBjYWxscyB0byB0aGlzIGZ1bmN0aW9uLlxuICogU3RlcCByZWdpc3RyYXRpb24gaXMgbm93IGlubGluZWQgYXMgYSBzZWxmLWNvbnRhaW5lZCBJSUZFIHRoYXQgd3JpdGVzXG4gKiBkaXJlY3RseSB0byB0aGUgZ2xvYmFsIE1hcCBhdCBTeW1ib2wuZm9yKFwiQHdvcmtmbG93L2NvcmUvL3JlZ2lzdGVyZWRTdGVwc1wiKS5cbiAqIFRoaXMgZnVuY3Rpb24gaXMga2VwdCBmb3IgaW50ZXJuYWwvdGVzdCB1c2Ugb25seS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyU3RlcEZ1bmN0aW9uKHN0ZXBJZDogc3RyaW5nLCBzdGVwRm46IFN0ZXBGdW5jdGlvbikge1xuICByZWdpc3RlcmVkU3RlcHMuc2V0KHN0ZXBJZCwgc3RlcEZuKTtcbiAgc3RlcEZuLnN0ZXBJZCA9IHN0ZXBJZDtcbn1cblxuLyoqXG4gKiBGaW5kIGEgcmVnaXN0ZXJlZCBzdGVwIGZ1bmN0aW9uIGJ5IG5hbWVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFN0ZXBGdW5jdGlvbihzdGVwSWQ6IHN0cmluZyk6IFN0ZXBGdW5jdGlvbiB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IGRpcmVjdE1hdGNoID0gcmVnaXN0ZXJlZFN0ZXBzLmdldChzdGVwSWQpO1xuICBpZiAoZGlyZWN0TWF0Y2gpIHtcbiAgICByZXR1cm4gZGlyZWN0TWF0Y2g7XG4gIH1cblxuICAvLyBTdXBwb3J0IGVxdWl2YWxlbnQgd29ya2Zsb3cgcGF0aCBhbGlhc2VzIGluIG1peGVkIHN5bWxpbmsgZW52aXJvbm1lbnRzLlxuICBmb3IgKGNvbnN0IGFsaWFzU3RlcElkIG9mIGdldFN0ZXBJZEFsaWFzQ2FuZGlkYXRlcyhzdGVwSWQpKSB7XG4gICAgY29uc3QgYWxpYXNNYXRjaCA9IHJlZ2lzdGVyZWRTdGVwcy5nZXQoYWxpYXNTdGVwSWQpO1xuICAgIGlmIChhbGlhc01hdGNoKSB7XG4gICAgICByZXR1cm4gYWxpYXNNYXRjaDtcbiAgICB9XG4gIH1cblxuICBjb25zdCBidWlsdGluQWxpYXNNYXRjaCA9IGdldEJ1aWx0aW5SZXNwb25zZVN0ZXBBbGlhcyhzdGVwSWQpO1xuICBpZiAoYnVpbHRpbkFsaWFzTWF0Y2gpIHtcbiAgICByZXR1cm4gYnVpbHRpbkFsaWFzTWF0Y2g7XG4gIH1cblxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG4vLyBOb3RlOiBfX3ByaXZhdGVfZ2V0Q2xvc3VyZVZhcnMgaXMgbm8gbG9uZ2VyIHJlLWV4cG9ydGVkIGhlcmUuXG4vLyBUaGUgU1dDIGNvbXBpbGVyIHBsdWdpbiBub3cgaW5saW5lcyBjbG9zdXJlIHZhcmlhYmxlIGFjY2VzcyBhcyBhXG4vLyBzZWxmLWNvbnRhaW5lZCBJSUZFIHRoYXQgcmVhZHMgZGlyZWN0bHkgZnJvbSB0aGUgZ2xvYmFsIEFzeW5jTG9jYWxTdG9yYWdlXG4vLyBhdCBTeW1ib2wuZm9yKFwiV09SS0ZMT1dfU1RFUF9DT05URVhUX1NUT1JBR0VcIikuXG5cbmV4cG9ydCBpbnRlcmZhY2UgV29ya2Zsb3dPcmNoZXN0cmF0b3JDb250ZXh0IHtcbiAgcnVuSWQ6IHN0cmluZztcbiAgZW5jcnlwdGlvbktleTogQ3J5cHRvS2V5IHwgdW5kZWZpbmVkO1xuICBnbG9iYWxUaGlzOiB0eXBlb2YgZ2xvYmFsVGhpcztcbiAgZXZlbnRzQ29uc3VtZXI6IEV2ZW50c0NvbnN1bWVyO1xuICAvKipcbiAgICogTWFwIG9mIHBlbmRpbmcgaW52b2NhdGlvbnMga2V5ZWQgYnkgY29ycmVsYXRpb25JZC5cbiAgICogVXNpbmcgTWFwIGluc3RlYWQgb2YgQXJyYXkgZm9yIE8oMSkgbG9va3VwL2RlbGV0ZSBvcGVyYXRpb25zLlxuICAgKi9cbiAgaW52b2NhdGlvbnNRdWV1ZTogTWFwPHN0cmluZywgUXVldWVJdGVtPjtcbiAgb25Xb3JrZmxvd0Vycm9yOiAoZXJyb3I6IEVycm9yKSA9PiB2b2lkO1xuICBnZW5lcmF0ZVVsaWQ6ICgpID0+IHN0cmluZztcbiAgZ2VuZXJhdGVOYW5vaWQ6ICgpID0+IHN0cmluZztcbiAgLyoqXG4gICAqIFNlcXVlbnRpYWwgcHJvbWlzZSBxdWV1ZSB0aGF0IGVuc3VyZXMgYWxsIGV2ZW50LWRyaXZlbiBwcm9taXNlIHJlc29sdXRpb25zXG4gICAqIChzdGVwIHJlc3VsdHMsIGhvb2sgcGF5bG9hZHMsIGZhaWx1cmVzLCBzdXNwZW5zaW9ucykgaGFwcGVuIGluIGV2ZW50IGxvZ1xuICAgKiBvcmRlci4gRXZlcnkgcmVzb2x2ZSwgcmVqZWN0LCBvciB3b3JrZmxvdyBlcnJvciBpcyBjaGFpbmVkIHRocm91Z2ggdGhpc1xuICAgKiBxdWV1ZSBzbyB0aGF0IGV2ZW4gaWYgaW5kaXZpZHVhbCBvcGVyYXRpb25zIHRha2UgdmFyaWFibGUgdGltZSAoZS5nLixcbiAgICogYXN5bmMgZGVjcnlwdGlvbiksIHByb21pc2VzIHJlc29sdmUgZGV0ZXJtaW5pc3RpY2FsbHkuXG4gICAqL1xuICBwcm9taXNlUXVldWU6IFByb21pc2U8dm9pZD47XG4gIC8qKlxuICAgKiBDb3VudGVyIG9mIGluLWZsaWdodCBhc3luYyBkYXRhIGRlbGl2ZXJ5IG9wZXJhdGlvbnMgKHN0ZXAgcmVzdWx0XG4gICAqIGh5ZHJhdGlvbiwgaG9vayBwYXlsb2FkIGh5ZHJhdGlvbikuIFN1c3BlbnNpb25zIG11c3Qgd2FpdCBmb3IgdGhpc1xuICAgKiB0byByZWFjaCAwIGJlZm9yZSBmaXJpbmcsIHRvIGF2b2lkIHByZWVtcHRpbmcgZGF0YSBkZWxpdmVyeS5cbiAgICovXG4gIHBlbmRpbmdEZWxpdmVyaWVzOiBudW1iZXI7XG59XG5cbi8qKlxuICogU2NoZWR1bGUgYSBjYWxsYmFjayB0byBmaXJlIG9ubHkgYWZ0ZXIgYWxsIHBlbmRpbmcgZGF0YSBkZWxpdmVyaWVzXG4gKiAoc3RlcCByZXN1bHRzLCBob29rIHBheWxvYWRzKSBhbmQgYXN5bmMgZGVzZXJpYWxpemF0aW9uIGhhdmUgY29tcGxldGVkLlxuICogVXNlcyBhIHBvbGxpbmcgbG9vcDogc2V0VGltZW91dCgwKSDihpIgY2hlY2sgcGVuZGluZ0RlbGl2ZXJpZXMg4oaSXG4gKiBpZiA+IDAsIHdhaXQgZm9yIHByb21pc2VRdWV1ZSDihpIgcmVwZWF0LiBUaGlzIGhhbmRsZXMgdGhlIG11bHRpLXJvdW5kXG4gKiBkZWxpdmVyeSBwYXR0ZXJuIHdoZXJlIGVhY2ggaG9vayBwYXlsb2FkIGRlbGl2ZXJ5IGN5Y2xlIGFwcGVuZHMgbmV3XG4gKiBhc3luYyB3b3JrIHRvIHRoZSBwcm9taXNlUXVldWUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzY2hlZHVsZVdoZW5JZGxlKFxuICBjdHg6IFdvcmtmbG93T3JjaGVzdHJhdG9yQ29udGV4dCxcbiAgZm46ICgpID0+IHZvaWRcbik6IHZvaWQge1xuICBjb25zdCBjaGVjayA9ICgpID0+IHtcbiAgICBpZiAoY3R4LnBlbmRpbmdEZWxpdmVyaWVzID4gMCkge1xuICAgICAgLy8gU3RpbGwgZGVsaXZlcmluZyBkYXRhIOKAlCB3YWl0IGZvciBxdWV1ZSB0byBkcmFpbiwgdGhlbiByZS1jaGVja1xuICAgICAgY3R4LnByb21pc2VRdWV1ZS50aGVuKCgpID0+IHtcbiAgICAgICAgc2V0VGltZW91dChjaGVjaywgMCk7XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgZm4oKTtcbiAgICB9XG4gIH07XG4gIHNldFRpbWVvdXQoY2hlY2ssIDApO1xufVxuIl19
720
+ /** Schedule a generation-guarded suspension after deliveries settle. */
721
+ export function scheduleWorkflowSuspension(ctx) {
722
+ const generation = ctx.suspensionGeneration;
723
+ scheduleWhenIdle(ctx, () => {
724
+ if (generation !== ctx.suspensionGeneration)
725
+ return;
726
+ ctx.onWorkflowError(new WorkflowSuspension(ctx.invocationsQueue, ctx.globalThis));
727
+ });
728
+ }
729
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJpdmF0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9wcml2YXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBRUgsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDeEQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBR2hELE9BQU8sRUFBa0Isa0JBQWtCLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFhakUsTUFBTSxrQkFBa0IsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLGlDQUFpQyxDQUFDLENBQUM7QUFFekUsTUFBTSxhQUFhLEdBRWYsVUFBVSxDQUFDO0FBRWYsd0RBQXdEO0FBQ3hELE1BQU0sZUFBZSxHQUFHLENBQUMsYUFBYSxDQUFDLGtCQUFrQixDQUFDLEtBQUssSUFBSSxHQUFHLEVBR25FLENBQUMsQ0FBQztBQUVMLE1BQU0sMkJBQTJCLEdBQUcsSUFBSSxHQUFHLENBQUM7SUFDMUMsaUNBQWlDO0lBQ2pDLHlCQUF5QjtJQUN6Qix5QkFBeUI7Q0FDMUIsQ0FBQyxDQUFDO0FBRUgsU0FBUyx3QkFBd0IsQ0FBQyxNQUFjO0lBQzlDLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDakMsSUFBSSxLQUFLLENBQUMsTUFBTSxLQUFLLENBQUMsSUFBSSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssTUFBTSxFQUFFLENBQUM7UUFDOUMsT0FBTyxFQUFFLENBQUM7SUFDWixDQUFDO0lBRUQsTUFBTSxVQUFVLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzVCLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN4QixNQUFNLGlCQUFpQixHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7SUFFNUMsTUFBTSxRQUFRLEdBQUcsQ0FBQyxlQUF1QixFQUFFLEVBQUU7UUFDM0MsSUFB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QyxHQUFHLENBQUMsdUJBQXVCLElBQUksR0FBRyxDQUFDLHVCQUF1QixDQUFDLElBQUksS0FBSyxDQUFDLENBQUMsQ0FDekUsQ0FBQztBQUNKLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FvQkc7QUFDSCxNQUFNLFVBQVUsZ0JBQWdCLENBQzlCLEdBQWdDLEVBQ2hDLEVBQWM7SUFFZCxNQUFNLEtBQUssR0FBRyxHQUFHLEVBQUU7UUFDakIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3pCLHVFQUF1RTtZQUN2RSxxRUFBcUU7WUFDckUscUVBQXFFO1lBQ3JFLEdBQUcsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRTtnQkFDekIsVUFBVSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztZQUN2QixDQUFDLENBQUMsQ0FBQztRQUNMLENBQUM7YUFBTSxDQUFDO1lBQ04sRUFBRSxFQUFFLENBQUM7UUFDUCxDQUFDO0lBQ0gsQ0FBQyxDQUFDO0lBQ0YsVUFBVSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztBQUN2QixDQUFDO0FBRUQsd0VBQXdFO0FBQ3hFLE1BQU0sVUFBVSwwQkFBMEIsQ0FDeEMsR0FBZ0M7SUFFaEMsTUFBTSxVQUFVLEdBQUcsR0FBRyxDQUFDLG9CQUFvQixDQUFDO0lBQzVDLGdCQUFnQixDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUU7UUFDekIsSUFBSSxVQUFVLEtBQUssR0FBRyxDQUFDLG9CQUFvQjtZQUFFLE9BQU87UUFDcEQsR0FBRyxDQUFDLGVBQWUsQ0FDakIsSUFBSSxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLEVBQUUsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUM3RCxDQUFDO0lBQ0osQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBVdGlscyB1c2VkIGJ5IHRoZSBidW5kbGVyIHdoZW4gdHJhbnNmb3JtaW5nIGNvZGVcbiAqL1xuXG5pbXBvcnQgeyBXb3JrZmxvd1J1bnRpbWVFcnJvciB9IGZyb20gJ0B3b3JrZmxvdy9lcnJvcnMnO1xuaW1wb3J0IHsgd2l0aFJlc29sdmVycyB9IGZyb20gJ0B3b3JrZmxvdy91dGlscyc7XG5pbXBvcnQgdHlwZSB7IFdvcmxkQ2FwYWJpbGl0aWVzIH0gZnJvbSAnQHdvcmtmbG93L3dvcmxkJztcbmltcG9ydCB0eXBlIHsgRXZlbnRzQ29uc3VtZXIgfSBmcm9tICcuL2V2ZW50cy1jb25zdW1lci5qcyc7XG5pbXBvcnQgeyB0eXBlIFF1ZXVlSXRlbSwgV29ya2Zsb3dTdXNwZW5zaW9uIH0gZnJvbSAnLi9nbG9iYWwuanMnO1xuaW1wb3J0IHR5cGUgeyBSZXBsYXlQYXlsb2FkQ2FjaGUgfSBmcm9tICcuL3JlcGxheS1wYXlsb2FkLWNhY2hlLmpzJztcbmltcG9ydCB0eXBlIHsgU2VyaWFsaXphYmxlIH0gZnJvbSAnLi9zY2hlbWFzLmpzJztcbmltcG9ydCB0eXBlIHsgUGF5bG9hZEtleSB9IGZyb20gJy4vc2VyaWFsaXphdGlvbi9lbmNyeXB0aW9uLmpzJztcblxuZXhwb3J0IHR5cGUgU3RlcEZ1bmN0aW9uPFxuICBBcmdzIGV4dGVuZHMgU2VyaWFsaXphYmxlW10gPSBhbnlbXSxcbiAgUmVzdWx0IGV4dGVuZHMgU2VyaWFsaXphYmxlIHwgdW5rbm93biA9IHVua25vd24sXG4+ID0gKCguLi5hcmdzOiBBcmdzKSA9PiBQcm9taXNlPFJlc3VsdD4pICYge1xuICBtYXhSZXRyaWVzPzogbnVtYmVyO1xuICBzdGVwSWQ/OiBzdHJpbmc7XG59O1xuXG5jb25zdCBSZWdpc3RlcmVkU3RlcHNLZXkgPSBTeW1ib2wuZm9yKCdAd29ya2Zsb3cvY29yZS8vcmVnaXN0ZXJlZFN0ZXBzJyk7XG5cbmNvbnN0IGdsb2JhbFN5bWJvbHM6IHR5cGVvZiBnbG9iYWxUaGlzICYge1xuICBbUmVnaXN0ZXJlZFN0ZXBzS2V5XT86IE1hcDxzdHJpbmcsIFN0ZXBGdW5jdGlvbj47XG59ID0gZ2xvYmFsVGhpcztcblxuLy8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0Fzc2lnbkluRXhwcmVzc2lvbnM6IC9cbmNvbnN0IHJlZ2lzdGVyZWRTdGVwcyA9IChnbG9iYWxTeW1ib2xzW1JlZ2lzdGVyZWRTdGVwc0tleV0gPz89IG5ldyBNYXA8XG4gIHN0cmluZyxcbiAgU3RlcEZ1bmN0aW9uXG4+KCkpO1xuXG5jb25zdCBCVUlMVElOX1JFU1BPTlNFX1NURVBfTkFNRVMgPSBuZXcgU2V0KFtcbiAgJ19fYnVpbHRpbl9yZXNwb25zZV9hcnJheV9idWZmZXInLFxuICAnX19idWlsdGluX3Jlc3BvbnNlX2pzb24nLFxuICAnX19idWlsdGluX3Jlc3BvbnNlX3RleHQnLFxuXSk7XG5cbmZ1bmN0aW9uIGdldFN0ZXBJZEFsaWFzQ2FuZGlkYXRlcyhzdGVwSWQ6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgY29uc3QgcGFydHMgPSBzdGVwSWQuc3BsaXQoJy8vJyk7XG4gIGlmIChwYXJ0cy5sZW5ndGggIT09IDMgfHwgcGFydHNbMF0gIT09ICdzdGVwJykge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIGNvbnN0IG1vZHVsZVBhdGggPSBwYXJ0c1sxXTtcbiAgY29uc3QgZm5OYW1lID0gcGFydHNbMl07XG4gIGNvbnN0IG1vZHVsZVBhdGhBbGlhc2VzID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgY29uc3QgYWRkQWxpYXMgPSAoYWxpYXNNb2R1bGVQYXRoOiBzdHJpbmcpID0+IHtcbiAgICBpZiAoYWxpYXNNb2R1bGVQYXRoICE9PSBtb2R1bGVQYXRoKSB7XG4gICAgICBtb2R1bGVQYXRoQWxpYXNlcy5hZGQoYWxpYXNNb2R1bGVQYXRoKTtcbiAgICB9XG4gIH07XG5cbiAgaWYgKG1vZHVsZVBhdGguc3RhcnRzV2l0aCgnLi93b3JrZmxvd3MvJykpIHtcbiAgICBjb25zdCB3b3JrZmxvd1JlbGF0aXZlUGF0aCA9IG1vZHVsZVBhdGguc2xpY2UoJy4vJy5sZW5ndGgpO1xuICAgIGFkZEFsaWFzKGAuL2V4YW1wbGUvJHt3b3JrZmxvd1JlbGF0aXZlUGF0aH1gKTtcbiAgICBhZGRBbGlhcyhgLi9zcmMvJHt3b3JrZmxvd1JlbGF0aXZlUGF0aH1gKTtcbiAgfSBlbHNlIGlmIChtb2R1bGVQYXRoLnN0YXJ0c1dpdGgoJy4vZXhhbXBsZS93b3JrZmxvd3MvJykpIHtcbiAgICBjb25zdCB3b3JrZmxvd1JlbGF0aXZlUGF0aCA9IG1vZHVsZVBhdGguc2xpY2UoJy4vZXhhbXBsZS8nLmxlbmd0aCk7XG4gICAgYWRkQWxpYXMoYC4vJHt3b3JrZmxvd1JlbGF0aXZlUGF0aH1gKTtcbiAgICBhZGRBbGlhcyhgLi9zcmMvJHt3b3JrZmxvd1JlbGF0aXZlUGF0aH1gKTtcbiAgfSBlbHNlIGlmIChtb2R1bGVQYXRoLnN0YXJ0c1dpdGgoJy4vc3JjL3dvcmtmbG93cy8nKSkge1xuICAgIGNvbnN0IHdvcmtmbG93UmVsYXRpdmVQYXRoID0gbW9kdWxlUGF0aC5zbGljZSgnLi9zcmMvJy5sZW5ndGgpO1xuICAgIGFkZEFsaWFzKGAuLyR7d29ya2Zsb3dSZWxhdGl2ZVBhdGh9YCk7XG4gICAgYWRkQWxpYXMoYC4vZXhhbXBsZS8ke3dvcmtmbG93UmVsYXRpdmVQYXRofWApO1xuICB9XG5cbiAgcmV0dXJuIEFycmF5LmZyb20oXG4gICAgbW9kdWxlUGF0aEFsaWFzZXMsXG4gICAgKGFsaWFzTW9kdWxlUGF0aCkgPT4gYHN0ZXAvLyR7YWxpYXNNb2R1bGVQYXRofS8vJHtmbk5hbWV9YFxuICApO1xufVxuXG5mdW5jdGlvbiBnZXRCdWlsdGluUmVzcG9uc2VTdGVwQWxpYXMoc3RlcElkOiBzdHJpbmcpOiBTdGVwRnVuY3Rpb24gfCB1bmRlZmluZWQge1xuICBpZiAoIUJVSUxUSU5fUkVTUE9OU0VfU1RFUF9OQU1FUy5oYXMoc3RlcElkKSkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBmb3IgKGNvbnN0IFtyZWdpc3RlcmVkU3RlcElkLCBzdGVwRm5dIG9mIHJlZ2lzdGVyZWRTdGVwcy5lbnRyaWVzKCkpIHtcbiAgICBpZiAocmVnaXN0ZXJlZFN0ZXBJZC5lbmRzV2l0aChgLy8ke3N0ZXBJZH1gKSkge1xuICAgICAgcmV0dXJuIHN0ZXBGbjtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVyIGEgc3RlcCBmdW5jdGlvbiB0byBiZSBzZXJ2ZWQgaW4gdGhlIHNlcnZlciBidW5kbGUuXG4gKiBBbHNvIHNldHMgdGhlIHN0ZXBJZCBwcm9wZXJ0eSBvbiB0aGUgZnVuY3Rpb24gZm9yIHNlcmlhbGl6YXRpb24gc3VwcG9ydC5cbiAqXG4gKiBOb3RlOiBUaGUgU1dDIGNvbXBpbGVyIHBsdWdpbiBubyBsb25nZXIgZ2VuZXJhdGVzIGNhbGxzIHRvIHRoaXMgZnVuY3Rpb24uXG4gKiBTdGVwIHJlZ2lzdHJhdGlvbiBpcyBub3cgaW5saW5lZCBhcyBhIHNlbGYtY29udGFpbmVkIElJRkUgdGhhdCB3cml0ZXNcbiAqIGRpcmVjdGx5IHRvIHRoZSBnbG9iYWwgTWFwIGF0IFN5bWJvbC5mb3IoXCJAd29ya2Zsb3cvY29yZS8vcmVnaXN0ZXJlZFN0ZXBzXCIpLlxuICogVGhpcyBmdW5jdGlvbiBpcyBrZXB0IGZvciBpbnRlcm5hbC90ZXN0IHVzZSBvbmx5LlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJTdGVwRnVuY3Rpb24oc3RlcElkOiBzdHJpbmcsIHN0ZXBGbjogU3RlcEZ1bmN0aW9uKSB7XG4gIHJlZ2lzdGVyZWRTdGVwcy5zZXQoc3RlcElkLCBzdGVwRm4pO1xuICBzdGVwRm4uc3RlcElkID0gc3RlcElkO1xufVxuXG4vKipcbiAqIEZpbmQgYSByZWdpc3RlcmVkIHN0ZXAgZnVuY3Rpb24gYnkgbmFtZVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0U3RlcEZ1bmN0aW9uKHN0ZXBJZDogc3RyaW5nKTogU3RlcEZ1bmN0aW9uIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgZGlyZWN0TWF0Y2ggPSByZWdpc3RlcmVkU3RlcHMuZ2V0KHN0ZXBJZCk7XG4gIGlmIChkaXJlY3RNYXRjaCkge1xuICAgIHJldHVybiBkaXJlY3RNYXRjaDtcbiAgfVxuXG4gIC8vIFN1cHBvcnQgZXF1aXZhbGVudCB3b3JrZmxvdyBwYXRoIGFsaWFzZXMgaW4gbWl4ZWQgc3ltbGluayBlbnZpcm9ubWVudHMuXG4gIGZvciAoY29uc3QgYWxpYXNTdGVwSWQgb2YgZ2V0U3RlcElkQWxpYXNDYW5kaWRhdGVzKHN0ZXBJZCkpIHtcbiAgICBjb25zdCBhbGlhc01hdGNoID0gcmVnaXN0ZXJlZFN0ZXBzLmdldChhbGlhc1N0ZXBJZCk7XG4gICAgaWYgKGFsaWFzTWF0Y2gpIHtcbiAgICAgIHJldHVybiBhbGlhc01hdGNoO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IGJ1aWx0aW5BbGlhc01hdGNoID0gZ2V0QnVpbHRpblJlc3BvbnNlU3RlcEFsaWFzKHN0ZXBJZCk7XG4gIGlmIChidWlsdGluQWxpYXNNYXRjaCkge1xuICAgIHJldHVybiBidWlsdGluQWxpYXNNYXRjaDtcbiAgfVxuXG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbi8vIE5vdGU6IF9fcHJpdmF0ZV9nZXRDbG9zdXJlVmFycyBpcyBubyBsb25nZXIgcmUtZXhwb3J0ZWQgaGVyZS5cbi8vIFRoZSBTV0MgY29tcGlsZXIgcGx1Z2luIG5vdyBpbmxpbmVzIGNsb3N1cmUgdmFyaWFibGUgYWNjZXNzIGFzIGFcbi8vIHNlbGYtY29udGFpbmVkIElJRkUgdGhhdCByZWFkcyBkaXJlY3RseSBmcm9tIHRoZSBnbG9iYWwgQXN5bmNMb2NhbFN0b3JhZ2Vcbi8vIGF0IFN5bWJvbC5mb3IoXCJXT1JLRkxPV19TVEVQX0NPTlRFWFRfU1RPUkFHRVwiKS5cblxuZXhwb3J0IGludGVyZmFjZSBXb3JrZmxvd09yY2hlc3RyYXRvckNvbnRleHQge1xuICBydW5JZDogc3RyaW5nO1xuICBlbmNyeXB0aW9uS2V5OiBQYXlsb2FkS2V5IHwgdW5kZWZpbmVkO1xuICB3b3JsZENhcGFiaWxpdGllcz86IFdvcmxkQ2FwYWJpbGl0aWVzO1xuICBnbG9iYWxUaGlzOiB0eXBlb2YgZ2xvYmFsVGhpcztcbiAgLyoqXG4gICAqIEluY3JlbWVudHMgd2hlbiBhIHN1c3BlbnNpb24gaXMgYWNjZXB0ZWQgYW5kIG9uIGV2ZXJ5IHJldGFpbmVkLXNlc3Npb25cbiAgICogcmVzdW1lLiBTdGVwLCBob29rLCB3YWl0LCBhbmQgYXR0cmlidXRlIHN1c3BlbnNpb24gc2lnbmFscyBjYXB0dXJlIGl0IHdoZW5cbiAgICogc2NoZWR1bGVkIGFuZCBuby1vcCBpZiBpdCBtb3ZlZCwgd2hpY2ggZHJvcHMgc2FtZS1ib3VuZGFyeSBzaWJsaW5nIHNpZ25hbHNcbiAgICogYW5kIHRpbWVycyBxdWV1ZWQgYXQgYm91bmRhcnkgTiB0aGF0IHdvdWxkIGZpcmUgYWZ0ZXIgdGhlIHNlc3Npb24gcmVzdW1lZFxuICAgKiBpbnRvIGJvdW5kYXJ5IE4rMS5cbiAgICovXG4gIHN1c3BlbnNpb25HZW5lcmF0aW9uOiBudW1iZXI7XG4gIGV2ZW50c0NvbnN1bWVyOiBFdmVudHNDb25zdW1lcjtcbiAgLyoqXG4gICAqIE1hcCBvZiBwZW5kaW5nIGludm9jYXRpb25zIGtleWVkIGJ5IGNvcnJlbGF0aW9uSWQuXG4gICAqIFVzaW5nIE1hcCBpbnN0ZWFkIG9mIEFycmF5IGZvciBPKDEpIGxvb2t1cC9kZWxldGUgb3BlcmF0aW9ucy5cbiAgICovXG4gIGludm9jYXRpb25zUXVldWU6IE1hcDxzdHJpbmcsIFF1ZXVlSXRlbT47XG4gIG9uV29ya2Zsb3dFcnJvcjogKGVycm9yOiBFcnJvcikgPT4gdm9pZDtcbiAgLyoqXG4gICAqIE1pbnRzIHRoZSBVTElEIGJvZHkgb2YgYSBjb3JyZWxhdGlvbiBpZC4gRXZlcnkgZW50aXR5IGEgcmVwbGF5IGNyZWF0ZXNcbiAgICogZHJhd3MgZnJvbSB0aGlzIG9uZSBtb25vdG9uaWMgc2VxdWVuY2UsIHNvIGFuIGlkIGlzIGFuIG9yZGluYWwgb3ZlciB0aGVcbiAgICogd2hvbGUgcnVuIGFuZCBib3RoIHJlcGxheXMgb2YgYSBydW4gbXVzdCBkcmF3IGluIHRoZSBzYW1lIG9yZGVyLlxuICAgKi9cbiAgZ2VuZXJhdGVVbGlkOiAoKSA9PiBzdHJpbmc7XG4gIC8qKlxuICAgKiBNb25vdG9uZSBjb3VudCBvZiBjb3JyZWxhdGlvbi1pZCBkcmF3cyB0aGlzIHJlcGxheSBoYXMgbWFkZS4gUHJvZ3Jlc3NcbiAgICogbWV0cmljIGZvciB7QGxpbmsgcXVpZXNjZUVhcmxpZXJDYXNjYWRlc306IGEgbWFjcm90YXNrIHR1cm4gaW4gd2hpY2ggaXRcbiAgICogZG9lcyBub3QgbW92ZSAoYW5kIG5vIGh5ZHJhdGlvbiBpcyBpbiBmbGlnaHQpIG1lYW5zIGV2ZXJ5IHdva2VuIGJyYW5jaCBoYXNcbiAgICogcnVuIGFzIGZhciBhcyBpdCBjYW4gd2l0aG91dCBhbm90aGVyIGRlbGl2ZXJ5LiBPcHRpb25hbCBzbyBsaWdodHdlaWdodFxuICAgKiB0ZXN0IGNvbnRleHRzIGRlZ3JhZGUgdG8gdGhlIHNpbmdsZS15aWVsZCBiZWhhdmlvci5cbiAgICovXG4gIHJlYWRvbmx5IG1pbnRDb3VudD86IG51bWJlcjtcbiAgZ2VuZXJhdGVOYW5vaWQ6ICgpID0+IHN0cmluZztcbiAgLyoqXG4gICAqIFNlcXVlbnRpYWwgcHJvbWlzZSBxdWV1ZSB0aGF0IGVuc3VyZXMgYWxsIGV2ZW50LWRyaXZlbiBwcm9taXNlIHJlc29sdXRpb25zXG4gICAqIChzdGVwIHJlc3VsdHMsIGhvb2sgcGF5bG9hZHMsIGZhaWx1cmVzLCBzdXNwZW5zaW9ucykgaGFwcGVuIGluIGV2ZW50IGxvZ1xuICAgKiBvcmRlci4gRXZlcnkgcmVzb2x2ZSwgcmVqZWN0LCBvciB3b3JrZmxvdyBlcnJvciBpcyBjaGFpbmVkIHRocm91Z2ggdGhpc1xuICAgKiBxdWV1ZSBzbyB0aGF0IGV2ZW4gaWYgaW5kaXZpZHVhbCBvcGVyYXRpb25zIHRha2UgdmFyaWFibGUgdGltZSAoZS5nLixcbiAgICogYXN5bmMgZGVjcnlwdGlvbiksIHByb21pc2VzIHJlc29sdmUgZGV0ZXJtaW5pc3RpY2FsbHkuXG4gICAqL1xuICBwcm9taXNlUXVldWU6IFByb21pc2U8dm9pZD47XG4gIC8qKlxuICAgKiBDb3VudGVyIG9mIGluLWZsaWdodCBhc3luYyBkYXRhIGRlbGl2ZXJ5IG9wZXJhdGlvbnMgKHN0ZXAgcmVzdWx0XG4gICAqIGh5ZHJhdGlvbiwgaG9vayBwYXlsb2FkIGh5ZHJhdGlvbiwgYWJvcnQgc2lnbmFsIGh5ZHJhdGlvbikuIFN1c3BlbnNpb25zXG4gICAqIG11c3Qgd2FpdCBmb3IgdGhpcyB0byByZWFjaCAwIGJlZm9yZSBmaXJpbmcsIHRvIGF2b2lkIHByZWVtcHRpbmcgZGF0YVxuICAgKiBkZWxpdmVyeSwgZS5nLiBkZWh5ZHJhdGluZyBhIHN0ZXAncyBhcmd1bWVudHMgd2hpbGUgYW4gYWJvcnQgdGhhdCBzaG91bGRcbiAgICogYmUgcmVmbGVjdGVkIGluIHRob3NlIGFyZ3VtZW50cyBpcyBzdGlsbCBoeWRyYXRpbmcgaXRzIHJlYXNvbi5cbiAgICovXG4gIHBlbmRpbmdEZWxpdmVyaWVzOiBudW1iZXI7XG4gIC8qKlxuICAgKiBPcmRlcmVkIHJlZ2lzdHJ5IG9mIGluLWZsaWdodCBcImJyYW5jaC1kZWNpZGluZ1wiIGRlbGl2ZXJpZXM6IHRoZVxuICAgKiByZXNvbHV0aW9ucyBhIHdvcmtmbG93IHR5cGljYWxseSBgUHJvbWlzZS5yYWNlYHMgb24sIG9yIGF3YWl0cyBmcm9tXG4gICAqIGluZGVwZW5kZW50IGNvbmN1cnJlbnQgYnJhbmNoZXM6IGhvb2sgcGF5bG9hZHMgKGBob29rX3JlY2VpdmVkYCksIHdhaXRcbiAgICogY29tcGxldGlvbnMgKGB3YWl0X2NvbXBsZXRlZGApLCBhbmQgc3RlcCByZXN1bHRzIChgc3RlcF9jb21wbGV0ZWRgIC9cbiAgICogYHN0ZXBfZmFpbGVkYCkuIEtleWVkIGJ5IHRoZSBkZWxpdmVyeSdzIHBvc2l0aW9uIChpbmRleCkgaW4gdGhlIGNvbnN1bWVkXG4gICAqIGV2ZW50IGxvZy5cbiAgICpcbiAgICogVGhlIHByb2JsZW06IGVhY2ggb2YgdGhlc2UgcmVzb2x1dGlvbnMgcmVhY2hlcyB3b3JrZmxvdyBjb2RlIGFmdGVyIGFcbiAgICogZGlmZmVyZW50LCB3b3JrbG9hZC1kZXBlbmRlbnQgbnVtYmVyIG9mIG1pY3JvdGFzayBob3BzLiBBIGJ1ZmZlcmVkIGhvb2tcbiAgICogcGF5bG9hZCBpcyBvYnNlcnZlZCB2aWEgdGhlIGFzeW5jIGhvb2sgaXRlcmF0b3IgKGB5aWVsZCBhd2FpdCB0aGlzYCksXG4gICAqIGNvc3RpbmcgZXh0cmEgaG9wczsgYSBgd2FpdF9jb21wbGV0ZWRgIHJlc29sdmVzIHdpdGggZmV3ZXIsIGFuZCBhIHJldXNlZFxuICAgKiBzbGVlcCBjYW4gcmVzb2x2ZSBpbiBhbiBlbnRpcmVseSBlYXJsaWVyIGxvb3AgaXRlcmF0aW9uOyBhIHN0ZXAgcmVzdWx0IGlzXG4gICAqIGdhdGVkIG9uIGh5ZHJhdGlvbiB3aG9zZSBjb3N0IHZhcmllcyBiZXR3ZWVuIHJlcGxheXMgb2YgdGhlIFNBTUVcbiAgICogaW52b2NhdGlvbjogdGhlIGZpcnN0IHJlcGxheSBwYXlzIHRoZSBmdWxsIGRlY3J5cHQvZGVjb21wcmVzcy9yZXZpdmUsXG4gICAqIHdoaWxlIGxhdGVyIHJlcGxheXMgc2hhcmluZyB0aGUgaW52b2NhdGlvbidzIGBSZXBsYXlQYXlsb2FkQ2FjaGVgXG4gICAqIG1lbW8taGl0IHNtYWxsIHByaW1pdGl2ZSByZXN1bHRzIGFuZCByZXNvbHZlIGluIG9uZSBvciB0d28gaG9wcy4gRWl0aGVyXG4gICAqIHdheSwgdGhlIHJlc29sdXRpb24gdGhhdCB0aGUgY29tbWl0dGVkIGV2ZW50IGxvZyBvcmRlcmVkIGZpcnN0IGNhbiBsb3NlIGFcbiAgICogYFByb21pc2UucmFjZWAgKG9yIGEgYHVzZVN0ZXBgIFVMSUQgYWxsb2NhdGlvbikgdG8gYSBmYXN0ZXItIG9yXG4gICAqIGFscmVhZHktcmVzb2x2ZWQgY29tcGV0aXRvciwgZGl2ZXJnaW5nIGZyb20gdGhlIGxvZyBhbmQgc3VyZmFjaW5nIGFzXG4gICAqIGBDb3JydXB0ZWRFdmVudExvZ0Vycm9yYC5cbiAgICpcbiAgICogVGhlIGZpeCBpcyBhIHN0cmljdCwgZGV0ZXJtaW5pc3RpYyBkZWxpdmVyeSBvcmRlciBhbmNob3JlZCBvblxuICAgKiBldmVudC1sb2cgcG9zaXRpb246IGEgZGVsaXZlcnkgZG9lcyBub3QgcmVzb2x2ZSB0byB0aGUgd29ya2Zsb3cgdW50aWxcbiAgICogZXZlcnkgcmVsZXZhbnQgZWFybGllci1pbi1sb2cgZGVsaXZlcnkgaGFzIGJlZW4gZGVsaXZlcmVkLiBCZWNhdXNlIHRoZVxuICAgKiBnYXRlIGlzIFwidGhlIGVhcmxpZXIgZGVsaXZlcnkgcmVzb2x2ZWRcIiwgbm90IFwid29uIGEgdGltaW5nIHJhY2VcIiwgdGhlXG4gICAqIG91dGNvbWUgaXMgaW5kZXBlbmRlbnQgb2YgbWljcm90YXNrIGhvcHMsIGh5ZHJhdGlvbi9kZWNyeXB0aW9uIHRpbWUsXG4gICAqIGFuZCBgUHJvbWlzZS5yYWNlYCBhcmd1bWVudCBvcmRlci4gV2hpY2ggZWFybGllciBraW5kcyBhIGRlbGl2ZXJ5IGRlZmVyc1xuICAgKiBiZWhpbmQgaXMgc3BlbGxlZCBvdXQgb24ge0BsaW5rIGF3YWl0RWFybGllckRlbGl2ZXJpZXN9LlxuICAgKlxuICAgKiBJbmRleCBpcyB1c2VkIHJhdGhlciB0aGFuIHRoZSBgZXZlbnRJZGAgc3RyaW5nIGJlY2F1c2UgYGV2ZW50SWRgIGlzIGFuXG4gICAqIG9wYXF1ZSwgd29ybGQtYXNzaWduZWQgdmFsdWUgbm90IGd1YXJhbnRlZWQgdG8gc29ydCBpbiBjcmVhdGlvbiBvcmRlclxuICAgKiAob25seSB0aGUgYnVuZGxlZCBVTElEIHdvcmxkcyBoYXBwZW4gdG8pLlxuICAgKlxuICAgKiBPcHRpb25hbCBzbyBvbGRlci9vdXQtb2YtdHJlZSBjb250ZXh0cyAoYW5kIGxpZ2h0d2VpZ2h0IHRlc3QgaGFybmVzc2VzKVxuICAgKiB0aGF0IGRvIG5vdCBpbml0aWFsaXplIGl0IGRlZ3JhZGUgZ3JhY2VmdWxseSB0byB0aGUgcHJldmlvdXMgYmVoYXZpb3IuXG4gICAqL1xuICBwZW5kaW5nRGVsaXZlcnlCYXJyaWVycz86IE1hcDxudW1iZXIsIERlbGl2ZXJ5QmFycmllckVudHJ5PjtcbiAgLyoqXG4gICAqIEludm9jYXRpb24tc2NvcGVkIGNhY2hlIG9mIHByZXBhcmVkIHNlcmlhbGl6ZWQgcGF5bG9hZHMgYW5kIGltbXV0YWJsZSBmaW5hbFxuICAgKiB2YWx1ZXMuIFByZXBhcmVkIGJ5dGVzIHN1cnZpdmUgZnJlc2ggcmVwbGF5IFZNczsgb2JqZWN0IGdyYXBocyBkbyBub3QuXG4gICAqL1xuICByZXBsYXlQYXlsb2FkQ2FjaGU6IFJlcGxheVBheWxvYWRDYWNoZTtcbn1cblxuLyoqIFRoZSBraW5kIG9mIGJyYW5jaC1kZWNpZGluZyBkZWxpdmVyeSBhIGJhcnJpZXIgcmVwcmVzZW50cy4gKi9cbmV4cG9ydCB0eXBlIERlbGl2ZXJ5S2luZCA9ICdob29rJyB8ICd3YWl0JyB8ICdzdGVwJztcblxuaW50ZXJmYWNlIERlbGl2ZXJ5QmFycmllckVudHJ5IHtcbiAga2luZDogRGVsaXZlcnlLaW5kO1xuICAvKiogUmVzb2x2ZXMgb25jZSB0aGlzIGRlbGl2ZXJ5IGlzIGhhbmRlZCB0byB0aGUgd29ya2Zsb3cgb3IgcmV0aXJlZC4gKi9cbiAgcmVsZWFzZWQ6IFByb21pc2U8dm9pZD47XG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoaXMgZGVsaXZlcnkgaXMgY29tbWl0dGVkIHRvIHJlYWNoaW5nIHRoZSB3b3JrZmxvdyB3aXRob3V0IGFueVxuICAgKiBmdXJ0aGVyIGFjdGlvbiBieSB3b3JrZmxvdyBjb2RlLiBUcnVlIGZvciB3YWl0IGNvbXBsZXRpb25zIGFuZCBzdGVwXG4gICAqIHJlc3VsdHMsIHdoaWNoIGFsd2F5cyByZXNvbHZlIGZyb20gdGhlaXIgb3duIGNoYWluLCBhbmQgZm9yIGEgaG9vayBwYXlsb2FkXG4gICAqIHRoYXQgYWxyZWFkeSBoYWQgYSB3YWl0aW5nIGNvbnN1bWVyIHdoZW4gaXQgd2FzIGNvbnN1bWVkLlxuICAgKlxuICAgKiBGYWxzZSBmb3IgYSBCVUZGRVJFRCBob29rIHBheWxvYWQgbm8gY29uc3VtZXIgaGFzIGNsYWltZWQgeWV0OiBpdCBpc1xuICAgKiBkZWxpdmVyZWQgYnkgYGNsYWltKClgLCBpLmUuIHdoZW5ldmVyIHRoZSB3b3JrZmxvdyBuZXh0IHJlYWRzIHRoZSBob29rLFxuICAgKiB3aGljaCBtYXkgYmUgY2F1c2FsbHkgKmFmdGVyKiBhIGxhdGVyLWluLWxvZyBkZWxpdmVyeS4gYGFybSgpYCBmbGlwcyBpdFxuICAgKiBvbmNlIGEgY29uc3VtZXIgdGFrZXMgdGhlIHBheWxvYWQuXG4gICAqL1xuICBhcm1lZDogYm9vbGVhbjtcbiAgLyoqIFdoZXRoZXIgdGhpcyBlbnRyeSBoYXMgYmVlbiByZW1vdmVkIGFuZCBpdHMgYHJlbGVhc2VkYCBwcm9taXNlIHNldHRsZWQuICovXG4gIHJldGlyZWQ6IGJvb2xlYW47XG4gIC8qKlxuICAgKiBSZXRpcmUgdGhpcyBlbnRyeTogcmVzb2x2ZSBgcmVsZWFzZWRgIGFuZCByZW1vdmUgaXQgZnJvbSB0aGUgcmVnaXN0cnksXG4gICAqIHdpdGhvdXQgbWFya2luZyB0aGUgaGFuZGxlIGRlbGl2ZXJlZCB0byB0aGUgd29ya2Zsb3cuIEEgc2FmZXR5LXJldGlyZWRcbiAgICogYnVmZmVyZWQgcGF5bG9hZCBtYXkgdGhlcmVmb3JlIGluc3RhbGwgYSBmcmVzaCBlbnRyeSBpZiBpdCBpcyBjbGFpbWVkIGJ5XG4gICAqIGEgcmV0YWluZWQgVk0gbGF0ZXIuIENhbGxlZCBvbmx5IGJ5IHRoZSBjb250ZXh0J3Mgc2FmZXR5LW5ldCBkaXNwZW5zZXJcbiAgICogKHtAbGluayBlbnN1cmVCYXJyaWVyU2FmZXR5TmV0fSksIGFuZCBvbmx5IG9uIHRoZSBsb3dlc3QtaW5kZXggZW50cnkgYXRcbiAgICogZGVsaXZlcnkgaWRsZS4gSWRlbXBvdGVudC5cbiAgICovXG4gIHJldGlyZTogKCkgPT4gdm9pZDtcbn1cblxuLyoqXG4gKiBXaGljaCBlYXJsaWVyIGtpbmRzIGVhY2ggZGVsaXZlcnkga2luZCBkZWZlcnMgYmVoaW5kLiBDaG9zZW4gc28gdGhhdCBubyBraW5kXG4gKiBibG9ja3Mgb24gYSBwZWVyIGl0IGRvZXMgbm90IG5lZWQgdG86XG4gKlxuICogIC0gYSBob29rIGRlZmVycyBiZWhpbmQgZWFybGllciBIT09LUywgV0FJVFMgYW5kIFNURVBTO1xuICogIC0gYSB3YWl0IGRlZmVycyBiZWhpbmQgZWFybGllciBIT09LUyBhbmQgU1RFUFMgKG5vdCBlYXJsaWVyIHdhaXRzLCBzaW5jZSBhXG4gKiAgICB3YWl0IG5ldmVyIG5lZWRzIHRvIHF1ZXVlIGJlaGluZCBhbm90aGVyIHdhaXQpO1xuICogIC0gYSBzdGVwIGRlZmVycyBiZWhpbmQgZWFybGllciBXQUlUUywgSE9PS1MgYW5kIFNURVBTLlxuICpcbiAqIFRoZSBzdGVwLWJlaGluZC1zdGVwIGVkZ2UgaXMgbm90IHJlZHVuZGFudCB3aXRoIHRoZSBzZXJpYWwgYHByb21pc2VRdWV1ZWAuXG4gKiBUaGUgcXVldWUgZml4ZXMgdGhlIG9yZGVyIGluIHdoaWNoIHN0ZXAgcmVzdWx0cyBhcmUgSFlEUkFURUQsIGJ1dCBhIHN0ZXAgbm9cbiAqIGxvbmdlciByZXNvbHZlcyBpbnNpZGUgaXRzIHF1ZXVlIHNsb3Q6IGl0IGNhcHR1cmVzIHRoZSBvdXRjb21lIHRoZXJlIGFuZFxuICogcmVzb2x2ZXMgZnJvbSBhIGRldGFjaGVkIGNvbnRpbnVhdGlvbiBvbmNlIGl0cyBiYXJyaWVyIGNsZWFycy4gVHdvIHN0ZXBzXG4gKiBhZ3JlZSBvbiB0aGF0IGNvbnRpbnVhdGlvbidzIG9yZGVyaW5nIG9ubHkgd2hpbGUgdGhleSBkZWZlciBiZWhpbmQgdGhlIHNhbWVcbiAqIHNldCwgd2hpY2ggaG9sZHMgd2hlbiB0aGV5IGFyZSBjb25zdW1lZCBpbiB0aGUgc2FtZSBkcmFpbiB3aW5kb3cgYnV0IG5vdFxuICogYWNyb3NzIHdpbmRvd3M6IGEgc3RlcCBjb25zdW1lZCBsYXRlciBjYW4gbWlzcyBhIHdhaXQvaG9vayBiYXJyaWVyIHRoYXQgYW5cbiAqIGVhcmxpZXIgc3RlcCBpcyBzdGlsbCBwYXJrZWQgb24sIGJlY2F1c2UgdGhlIGJhcnJpZXIgcmV0aXJlZCBpbiBiZXR3ZWVuLiBUaGVcbiAqIGVhcmxpZXIgc3RlcCBpcyB0aGVuIHdhaXRpbmcgb3V0IHRoZSBtYWNyb3Rhc2sgeWllbGQgYmVsb3cgd2hpbGUgdGhlIGxhdGVyXG4gKiBvbmUgcmVzb2x2ZXMgb24gbWljcm90YXNrcywgYW5kIG92ZXJ0YWtlcyBpdC4gU2VlXG4gKiBgZGVsaXZlcnktYmFycmllci1jb3ZlcmFnZS50ZXN0LnRzYC4gRGVmZXJyaW5nIGJlaGluZCBlYXJsaWVyIHN0ZXBzXG4gKiBjbG9zZXMgdGhhdCB3aW5kb3cgc3RydWN0dXJhbGx5OiB0aGUgZWFybGllciBzdGVwJ3MgYmFycmllciBpcyBzdGlsbFxuICogcmVnaXN0ZXJlZCBwcmVjaXNlbHkgYmVjYXVzZSBpdCBoYXMgbm90IGRlbGl2ZXJlZCB5ZXQuXG4gKlxuICogRXZlcnkgZWRnZSBwb2ludHMgZnJvbSBhIGxhdGVyIGxvZyBpbmRleCB0byBhIHN0cmljdGx5IGVhcmxpZXIgb25lLCBzbyB0aGVcbiAqIHdhaXQtZm9yIGdyYXBoIGNhbiBuZXZlciBjb250YWluIGEgY3ljbGUuXG4gKi9cbmNvbnN0IERFRkVSX0JFSElORDogUmVjb3JkPERlbGl2ZXJ5S2luZCwgcmVhZG9ubHkgRGVsaXZlcnlLaW5kW10+ID0ge1xuICBob29rOiBbJ2hvb2snLCAnd2FpdCcsICdzdGVwJ10sXG4gIHdhaXQ6IFsnaG9vaycsICdzdGVwJ10sXG4gIHN0ZXA6IFsnd2FpdCcsICdob29rJywgJ3N0ZXAnXSxcbn07XG5cbi8qKlxuICogV2hldGhlciBhIGRlbGl2ZXJ5IG9mIGBraW5kYCBhdCBsb2cgaW5kZXggYGluZGV4YCBnYXRlcyBvbiB0aGUgZWFybGllclxuICogcmVnaXN0cnkgZW50cnkgYG90aGVyYCAoYXQgYG90aGVySW5kZXhgKS5cbiAqXG4gKiBTaW5nbGUgc291cmNlIG9mIHRydXRoIGZvciB0aGF0IHF1ZXN0aW9uLCBjYWxsZWQgYnkgYm90aFxuICoge0BsaW5rIGF3YWl0RWFybGllckRlbGl2ZXJpZXN9ICh3aGljaCBhd2FpdHMgd2hhdCBpdCBnYXRlcyBvbikgYW5kXG4gKiB7QGxpbmsgY29tcHV0ZVJlc29sdmVzT25JdHNPd259ICh3aGljaCByZWN1cnNlcyBpbnRvIHdoYXQgaXQgZ2F0ZXMgb24pLlxuICogVGhvc2UgdHdvIE1VU1QgYWdyZWUgZXhhY3RseSwgYW5kIHRoZSBkb2MgYmxvY2sgb25cbiAqIHtAbGluayBhd2FpdEVhcmxpZXJEZWxpdmVyaWVzfSBzdGFrZXMgZGVhZGxvY2stZnJlZWRvbSBvbiBpdCwgc28gdGhlXG4gKiBjb25kaXRpb24gbGl2ZXMgaGVyZSByYXRoZXIgdGhhbiBiZWluZyBzcGVsbGVkIG91dCB0d2ljZS5cbiAqXG4gKiBPbmUgZGVsaWJlcmF0ZSBleGNlcHRpb246IHRoZSBsb2ctb3JkZXItZHJhd3MgdHVybnN0aWxlIGluXG4gKiB7QGxpbmsgcXVpZXNjZUVhcmxpZXJDYXNjYWRlc30gd2FpdHMgb24gQU5ZIGxvd2VyIGFybWVkIGVudHJ5LCBhIHN0cmljdGx5XG4gKiB3aWRlciByZWxhdGlvbiB0aGFuIHRoaXMgb25lLiBXaHkgdGhhdCB3aWR0aCBjYW5ub3QgZGVhZGxvY2sgdGhlXG4gKiBzYWZldHktbmV0IGRpc3BlbnNlciBpcyBhcmd1ZWQgYXQgdGhlIHR1cm5zdGlsZSBpdHNlbGYuXG4gKi9cbmZ1bmN0aW9uIGdhdGVzT24oXG4gIGtpbmQ6IERlbGl2ZXJ5S2luZCxcbiAgaW5kZXg6IG51bWJlcixcbiAgb3RoZXJJbmRleDogbnVtYmVyLFxuICBvdGhlcjogRGVsaXZlcnlCYXJyaWVyRW50cnlcbik6IGJvb2xlYW4ge1xuICBpZiAob3RoZXJJbmRleCA+PSBpbmRleCB8fCAhREVGRVJfQkVISU5EW2tpbmRdLmluY2x1ZGVzKG90aGVyLmtpbmQpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIC8vIEEgc3RlcCBza2lwcyBhbiBVTkFSTUVEIGVhcmxpZXIgZW50cnkgKGFuIHVuY2xhaW1lZCBidWZmZXJlZCBob29rXG4gIC8vIHBheWxvYWQpLiBTZWUgdGhlIGFzeW1tZXRyeSBkZXNjcmliZWQgb24gYGF3YWl0RWFybGllckRlbGl2ZXJpZXNgLiBUaGVcbiAgLy8gc2tpcCBpcyBkaXJlY3QsIG5ldmVyIHRyYW5zaXRpdmU6IGFybWVkIGVudHJpZXMgYXJlIHN0aWxsIGdhdGVkIG9uLCBldmVuXG4gIC8vIHdoZW4gdGhleSBhcmUgdGhlbXNlbHZlcyBwYXJrZWQgYmVoaW5kIHN1Y2ggYSBwYXlsb2FkLlxuICByZXR1cm4gIShraW5kID09PSAnc3RlcCcgJiYgIW90aGVyLmFybWVkKTtcbn1cblxuLyoqXG4gKiBXaGV0aGVyIGBlbnRyeWAgd2lsbCByZXNvbHZlIG9uIGl0cyBvd246IGl0IGlzIGFybWVkLCBhbmQgZXZlcnkgZWFybGllclxuICogZGVsaXZlcnkgaXQgYWN0dWFsbHkgZ2F0ZXMgb24gKHtAbGluayBnYXRlc09ufSkgd2lsbCBsaWtld2lzZSByZXNvbHZlIG9uIGl0c1xuICogb3duLlxuICpcbiAqIEEgc3RlcCBkb2VzIG5vdCBnYXRlIG9uIGFuIHVuY2xhaW1lZCBidWZmZXJlZCBwYXlsb2FkLCBzbyBzdWNoIGEgcGF5bG9hZFxuICogY2Fubm90IGtlZXAgaXQgZnJvbSByZXNvbHZpbmcuIEEgc3RlcCBET0VTIGdhdGUgb24gZWFybGllciBhcm1lZCB3YWl0cyBhbmRcbiAqIGhvb2tzLCBzbyBvbmUgcGFya2VkIGJlaGluZCBhbiB1bmNsYWltZWQgcGF5bG9hZCBtYWtlcyB0aGUgc3RlcFxuICogbm9uLXNlbGYtcmVzb2x2aW5nIGluIHR1cm4uIERpc2FncmVlaW5nIHdpdGgge0BsaW5rIGF3YWl0RWFybGllckRlbGl2ZXJpZXN9XG4gKiBoZXJlIHdvdWxkIG5vdCBiZSBhIGNvc21ldGljIHByb2JsZW06IHRoaXMgcHJlZGljYXRlIGlzIHdoYXRcbiAqIHtAbGluayBoYXNQYXJrZWRDb21taXR0ZWREZWxpdmVyeX0gdXNlcyB0byBkZWNpZGUgd2hldGhlciBpZGxlIGlzIHJlYWNoYWJsZSxcbiAqIGFuZCBhbiBlbnRyeSByZXBvcnRlZCBzZWxmLXJlc29sdmluZyB3aGlsZSBpdCBpcyBpbiBmYWN0IHBhcmtlZCBiZWhpbmQgYVxuICogcGF5bG9hZCB0aGF0IG9ubHkgdGhlIGlkbGUgc2FmZXR5IG5ldCBjYW4gcmV0aXJlIHdvdWxkIGdhdGUgaXRzIG93blxuICogcmV0aXJlbWVudC5cbiAqXG4gKiBSZWN1cnNpb24gdGVybWluYXRlcyBiZWNhdXNlIGV2ZXJ5IGVkZ2UgcG9pbnRzIHRvIGEgc3RyaWN0bHkgc21hbGxlciBpbmRleC5cbiAqIGBtZW1vYCBrZWVwcyB0aGUgd2FsayBsaW5lYXIgaW4gcmVnaXN0cnkgc2l6ZSwgYW5kIHRoZSByZWdpc3RyeSBpcyBub3Qgc21hbGxcbiAqIGJ5IGNvbnN0cnVjdGlvbjogYEV2ZW50c0NvbnN1bWVyYCBkcmFpbnMgY29uc2VjdXRpdmVseSBjb25zdW1hYmxlIGV2ZW50c1xuICogc3luY2hyb25vdXNseSB3aGlsZSBiYXJyaWVycyBvbmx5IHJldGlyZSBvbiBtaWNyb3Rhc2stZHJpdmVuIGRlbGl2ZXJpZXMsIHNvXG4gKiBhIGZhbi1vdXQgb2YgYFByb21pc2UucmFjZShbaG9vaywgc2xlZXBdKWAgYnJhbmNoZXMgYWNjdW11bGF0ZXMgb25lIGJhcnJpZXJcbiAqIHBlciBicmFuY2ggcGVyIGtpbmQuIFRoZSBtZW1vIE1VU1QgYmUgcGVyLWNhbGw6IGBhcm1lZGAgbXV0YXRlcyBiZXR3ZWVuXG4gKiBjYWxscyBhcyBidWZmZXJlZCBwYXlsb2FkcyBhcmUgY2xhaW1lZC5cbiAqXG4gKiBUaGUgbWVtbyBpcyBhbiBvcHRpbWl6YXRpb24sIG5vdCBhIGNvcnJlY3RuZXNzIHJlcXVpcmVtZW50LiBJdCBvbmNlIHdhcyBvbmU6XG4gKiBgYXdhaXRFYXJsaWVyRGVsaXZlcmllc2AgdXNlZCB0byBydW4gdGhpcyB3YWxrIGZvciBldmVyeSBlYXJsaWVyIGVudHJ5IG9mIGFcbiAqIHN0ZXAgZGVsaXZlcnksIHdpdGggbm8gZWFybHkgZXhpdCwgd2hpY2ggdW5tZW1vaXplZCBpcyBUKG4pID0gzqMgVChqKSxcbiAqIG1lYXN1cmVkIGF0IDQuM2U4IHJlY3Vyc2l2ZSBjYWxscyAoODRzKSBmb3IgNDAgYWx0ZXJuYXRpbmcgYXJtZWQgaG9vay93YWl0XG4gKiBiYXJyaWVycy4gVGhhdCBjYWxsIHNpdGUgaXMgZ29uZTsgYSBzdGVwIG5vdyB0ZXN0cyBgYXJtZWRgIGRpcmVjdGx5LiBUaGUgb25lXG4gKiBzdXJ2aXZpbmcgY2FsbGVyLCB7QGxpbmsgaGFzUGFya2VkQ29tbWl0dGVkRGVsaXZlcnl9LCBjYW5ub3QgcmVhY2ggdGhhdFxuICogc2hhcGU6IGl0IHJldHVybnMgYXQgdGhlIEZJUlNUIHNlbGYtcmVzb2x2aW5nIGVudHJ5LCBzbyBpdCBvbmx5IGV2ZXJcbiAqIGFkdmFuY2VzIHBhc3QgZW50cmllcyB0aGF0IGFyZSBub24tc2VsZi1yZXNvbHZpbmcsIGFuZCB0aG9zZSBzaG9ydC1jaXJjdWl0XG4gKiBvbiB0aGVpciBmaXJzdCBmYWxzZSBjaGlsZC4gRXZlcnkgZW50cnkgaXQgZXZhbHVhdGVzIHRoZXJlZm9yZSBoYXNcbiAqIGFsbC1mYWxzZSBwcmVkZWNlc3NvcnMgYW5kIHJldHVybnMgYWZ0ZXIgb25lIGNoaWxkLCBkZWdlbmVyYXRpbmcgdGhlIHdhbGsgdG9cbiAqIGEgY2hhaW4gKG1lYXN1cmVkOiA5OCBjYWxscyB1bm1lbW9pemVkIGZvciB0aGUgd29yc3QgNDAtYmFycmllciBzaGFwZSwgMVxuICogY2FsbCBmb3IgdGhlIHJlZ2lzdHJ5IGFib3ZlKS4gRG8gbm90IHJlc3RvcmUgYW4gZXhwb25lbnRpYWwgY2xhaW0gaGVyZVxuICogd2l0aG91dCByZXN0b3JpbmcgYSBjYWxsZXIgdGhhdCBjYW4gcHJvZHVjZSBpdC5cbiAqL1xuZnVuY3Rpb24gcmVzb2x2ZXNPbkl0c093bihcbiAgYmFycmllcnM6IE1hcDxudW1iZXIsIERlbGl2ZXJ5QmFycmllckVudHJ5PixcbiAgaW5kZXg6IG51bWJlcixcbiAgZW50cnk6IERlbGl2ZXJ5QmFycmllckVudHJ5LFxuICBtZW1vOiBNYXA8bnVtYmVyLCBib29sZWFuPlxuKTogYm9vbGVhbiB7XG4gIGNvbnN0IGNhY2hlZCA9IG1lbW8uZ2V0KGluZGV4KTtcbiAgaWYgKGNhY2hlZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIGNhY2hlZDtcbiAgfVxuICBjb25zdCByZXN1bHQgPSBjb21wdXRlUmVzb2x2ZXNPbkl0c093bihiYXJyaWVycywgaW5kZXgsIGVudHJ5LCBtZW1vKTtcbiAgbWVtby5zZXQoaW5kZXgsIHJlc3VsdCk7XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmZ1bmN0aW9uIGNvbXB1dGVSZXNvbHZlc09uSXRzT3duKFxuICBiYXJyaWVyczogTWFwPG51bWJlciwgRGVsaXZlcnlCYXJyaWVyRW50cnk+LFxuICBpbmRleDogbnVtYmVyLFxuICBlbnRyeTogRGVsaXZlcnlCYXJyaWVyRW50cnksXG4gIG1lbW86IE1hcDxudW1iZXIsIGJvb2xlYW4+XG4pOiBib29sZWFuIHtcbiAgaWYgKCFlbnRyeS5hcm1lZCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBmb3IgKGNvbnN0IFtvdGhlckluZGV4LCBvdGhlcl0gb2YgYmFycmllcnMpIHtcbiAgICBpZiAoIWdhdGVzT24oZW50cnkua2luZCwgaW5kZXgsIG90aGVySW5kZXgsIG90aGVyKSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGlmICghcmVzb2x2ZXNPbkl0c093bihiYXJyaWVycywgb3RoZXJJbmRleCwgb3RoZXIsIG1lbW8pKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG4gIHJldHVybiB0cnVlO1xufVxuXG4vKipcbiAqIEF3YWl0cywgaW4gc3RyaWN0IGV2ZW50LWxvZyBvcmRlciwgZXZlcnkgc3RpbGwtcmVnaXN0ZXJlZCBkZWxpdmVyeSB0aGF0IGlzXG4gKiBlYXJsaWVyIGluIHRoZSBsb2cgdGhhbiBgZXZlbnRJbmRleGAgYW5kIHRoYXQgYSBkZWxpdmVyeSBvZiBga2luZGAgZGVmZXJzXG4gKiBiZWhpbmQgKHNlZSB7QGxpbmsgREVGRVJfQkVISU5EfSksIHNvIHRoYXQgdGhpcyByZXNvbHV0aW9uIGlzIGhhbmRlZCB0byB0aGVcbiAqIHdvcmtmbG93IG9ubHkgYWZ0ZXIgYWxsIHJlbGV2YW50IGVhcmxpZXItaW4tbG9nIGRlbGl2ZXJpZXMgaGF2ZSBiZWVuLiBUaGlzXG4gKiBpcyB3aGF0IGtlZXBzIGEgYFByb21pc2UucmFjZWAgKG9yIHRoZSBVTElEIGEgZm9sbG93LXVwIGB1c2VTdGVwYCBkcmF3cyBvblxuICogYSBjb25jdXJyZW50IGJyYW5jaCkgZGV0ZXJtaW5pc3RpYyBhbmQgYWxpZ25lZCB3aXRoIHRoZSBjb21taXR0ZWQgZXZlbnRcbiAqIGxvZywgaW5kZXBlbmRlbnQgb2YgbWljcm90YXNrLWhvcCBjb3VudHMsIGh5ZHJhdGlvbiB0aW1lLCBvciByYWNlLWFyZ3VtZW50XG4gKiBvcmRlci4gV2hlbiB0aGlzIGRlbGl2ZXJ5IGRvZXMgaGF2ZSB0byB3YWl0LCBpdCBhbHNvIHlpZWxkcyBhIG1hY3JvdGFza1xuICogYWZ0ZXJ3YXJkcyBzbyB0aGUgZWFybGllciBkZWxpdmVyeSdzIGNvbnN1bWVyIGNhbiBydW4gdG8gaXRzIG93biBuZXh0XG4gKiBzdXNwZW5zaW9uIHBvaW50IGZpcnN0OyBzZWUgdGhlIGNvbW1lbnQgYXQgdGhhdCBgYXdhaXRgIGZvciB3aHkgb3JkZXJpbmcgdGhlXG4gKiBgcmVzb2x2ZSgpYCBjYWxscyBhbG9uZSBpcyBub3QgZW5vdWdoLlxuICpcbiAqIFdoYXQgY291bnRzIGFzIFwiZGVmZXJzIGJlaGluZFwiIGlzIHtAbGluayBnYXRlc09ufSwgc2hhcmVkIHdpdGhcbiAqIHtAbGluayBjb21wdXRlUmVzb2x2ZXNPbkl0c093bn0gc28gdGhlIHR3byBjYW5ub3QgZHJpZnQuXG4gKlxuICogT25lIGFzeW1tZXRyeTogYSBTVEVQIHJlc3VsdCBza2lwcyBhbnkgZWFybGllciBkZWxpdmVyeSB0aGF0IGlzIFVOQVJNRUQsXG4gKiBpLmUuIGEgYnVmZmVyZWQgaG9vayBwYXlsb2FkIG5vIGNvbnN1bWVyIGhhcyBjbGFpbWVkLiBTdWNoIGEgcGF5bG9hZCBpc1xuICogZGVsaXZlcmVkIG9ubHkgd2hlbiB0aGUgd29ya2Zsb3cgbmV4dCByZWFkcyB0aGUgaG9vaywgYW5kIHJlYWNoaW5nIHRoYXQgcmVhZFxuICogb2Z0ZW4gcmVxdWlyZXMgdGhlIHN0ZXAgcmVzdWx0IGl0c2VsZiAoYGF3YWl0IHN0ZXBYKClgIGJlZm9yZSB0aGVcbiAqIHJlYWQpLiBHYXRpbmcgdGhlIHN0ZXAgb24gaXQgd291bGQgc3RhbGwgdGhlIHdvcmtmbG93IHVudGlsIHRoZSBiYXJyaWVyJ3NcbiAqIGlkbGUgc2FmZXR5IG5ldCBmaXJlcywgd2hpY2ggdGhlbiByZWxlYXNlcyBldmVyeSBkZWxpdmVyeSBxdWV1ZWQgYmVoaW5kIHRoYXRcbiAqIHBheWxvYWQgYXQgb25jZSwgbG9zaW5nIGV4YWN0bHkgdGhlIHJhY2UgdGhpcyBvcmRlcmluZyBleGlzdHMgdG8gcHJvdGVjdC5cbiAqIFdhaXRzIGFuZCBob29rcyBrZWVwIGdhdGluZyBvbiB1bmNsYWltZWQgcGF5bG9hZHM6IGZvciB0aGVtLCB3YWl0aW5nIGZvciB0aGVcbiAqIGNsYWltIElTIHRoZSBvcmRlcmluZyBndWFyYW50ZWUgKGEgYHdhaXRfY29tcGxldGVkYCBtdXN0IG5vdCBwcmVlbXB0IGFcbiAqIHBheWxvYWQgdGhlIGxvZyBvcmRlcmVkIGZpcnN0KS5cbiAqXG4gKiBUaGUgc2tpcCBpcyBkaXJlY3QsIG5ldmVyIHRyYW5zaXRpdmUuIEEgc3RlcCBzdGlsbCBnYXRlcyBvbiBhbiBlYXJsaWVyIEFSTUVEXG4gKiB3YWl0IG9yIGhvb2ssIGluY2x1ZGluZyBvbmUgdGhhdCBpcyBpdHNlbGYgcGFya2VkIGJlaGluZCBhbiB1bmNsYWltZWRcbiAqIHBheWxvYWQuIFNraXBwaW5nIHRob3NlIHRvbyB3b3VsZCBpbnZlcnQgbG9nIG9yZGVyIGZvciB0aGUgY29tbW9uZXN0IHNoYXBlXG4gKiB0aGVyZSBpczogYSB3b3JrZmxvdyB0aGF0IGNyZWF0ZXMgYSBob29rIGl0IGRvZXMgbm90IHJlYWQgb24gdGhpcyBicmFuY2gsXG4gKiByYWNlcyBgc3RlcGAgYWdhaW5zdCBgc2xlZXBgLCBhbmQgaGFzIHRoZSBsb2cgc2F5IHRoZSBzbGVlcCB3b24uIFRoZSBzdGVwXG4gKiB3b3VsZCB0aGVuIG92ZXJ0YWtlIHRoZSB3YWl0LCBib3RoIGJyYW5jaGVzIHdvdWxkIHN3YXAgdGhlIGNvcnJlbGF0aW9uIGlkc1xuICogdGhleSBkcmF3IG5leHQsIGFuZCByZXBsYXkgd291bGQgZGl2ZXJnZS4gU2VlXG4gKiBgc3RlcC1kZWxpdmVyeS1vcmRlcmluZy50ZXN0LnRzYC4gV2FpdGluZyBpbnN0ZWFkIGlzIHNhZmUgYmVjYXVzZSB0aGVcbiAqIHBheWxvYWQncyBvd24gaWRsZSBzYWZldHkgbmV0IHJldGlyZXMgaXQgYW5kIHRoZSB3aG9sZSBjaGFpbiB0aGVuIGRlbGl2ZXJzXG4gKiBpbiBsb2cgb3JkZXI7IHtAbGluayBoYXNQYXJrZWRDb21taXR0ZWREZWxpdmVyeX0gZGVsaWJlcmF0ZWx5IHJlcG9ydHMgc3VjaCBhXG4gKiBzdGVwIGFzIG5vdCBzZWxmLXJlc29sdmluZyBzbyB0aGF0IGlkbGUgc3RheXMgcmVhY2hhYmxlLlxuICpcbiAqIFwiVGhlIHdob2xlIGNoYWluIHRoZW4gZGVsaXZlcnMgaW4gbG9nIG9yZGVyXCIgcmVzdHMgb24gdGhlIFBBWUxPQUQncyBiYXJyaWVyXG4gKiBiZWluZyByZXRpcmVkIGJlZm9yZSB0aGF0IG9mIGFueXRoaW5nIHBhcmtlZCBiZWhpbmQgaXQuIFRoYXQgb3JkZXIgaXNcbiAqIHN0cnVjdHVyYWw6IHNhZmV0eS1uZXQgcmV0aXJlbWVudHMgZ28gdGhyb3VnaCBvbmUgcGVyLWNvbnRleHQgZGlzcGVuc2VyIHRoYXRcbiAqIG9ubHkgZXZlciByZXRpcmVzIHRoZSBsb3dlc3QtaW5kZXggZW50cnkgYXQgZGVsaXZlcnkgaWRsZSwgYW5kIGV2ZXJ5XG4gKiByZXRpcmVtZW50IHRoYXQgd2FrZXMgYSBjaGFpbiBmbGlwcyB7QGxpbmsgaGFzUGFya2VkQ29tbWl0dGVkRGVsaXZlcnl9IGJhY2tcbiAqIHRvIHRydWUsIHJlLWJsb2NraW5nIHRoZSBkaXNwZW5zZXIgdW50aWwgdGhlIGNoYWluIGhhcyBkcmFpbmVkLiBTZWVcbiAqIHtAbGluayBlbnN1cmVCYXJyaWVyU2FmZXR5TmV0fS4gKFRoaXMgdXNlZCB0byByZXN0IG9uIHRoZSBGSUZPIG9mIG9uZSBpZGxlXG4gKiBwb2xsIHBlciBiYXJyaWVyLCB3aGljaCBoZWxkIGZvciBhIHNpbmdsZSBwYXJrZWQgc2VnbWVudCBidXQgZGVjYXllZCB0b1xuICogdGltaW5nIG5vaXNlIHdpdGggc2V2ZXJhbDogdGhlIHJlbGVhc2Ugb3JkZXIsIGFuZCB0aGVyZWZvcmUgdGhlIFVMSURzXG4gKiBkcmF3biBieSB0aGUgd29rZW4gYnJhbmNoZXMsIHRoZW4gZGVwZW5kZWQgb24gaG93IG11Y2ggbG9nIHRoZSByZXBsYXkgaGFkXG4gKiBsb2FkZWQuIHN0b3JtLWxvZy1yZXBsYXkudGVzdC50cyByZXBsYXlzIGEgcHJvZHVjdGlvbiBsb2cgY29ycnVwdGVkIGV4YWN0bHlcbiAqIHRoYXQgd2F5LilcbiAqL1xuLyoqXG4gKiBXaGV0aGVyIGNvcnJlbGF0aW9uLWlkIGRyYXcgb3JkZXIgaXMgcGlubmVkIHRvIGV2ZW50LWxvZyBvcmRlci4gRGVmYXVsdCBPTjpcbiAqIG9ubHkgdGhlIGxpdGVyYWwgc3RyaW5nIGBXT1JLRkxPV19MT0dfT1JERVJfRFJBV1M9MGAgb3B0cyBvdXQuIGA9ZmFsc2VgLFxuICogYD1vZmZgLCBhbmQgZXZlcnkgb3RoZXIgdmFsdWUga2VlcCBpdCBlbmFibGVkLiBSZWFkIHBlciBjYWxsIHNvIHRlc3RzIGNhblxuICogZmxpcCBpdC5cbiAqXG4gKiBPZmYsIGEgZGVsaXZlcnkgdGhhdCBoYWQgdG8gZGVmZXIgeWllbGRzIE9ORSBtYWNyb3Rhc2sgYWZ0ZXIgaXRzXG4gKiBwcmVkZWNlc3NvcnMgcmVzb2x2ZS4gVGhpcyBpcyBlbm91Z2ggZm9yIHNob3J0IGNvbnN1bWVycywgYnV0IGEgd29rZW4gYnJhbmNoXG4gKiB3aG9zZSBwYXRoIHRvIGl0cyBuZXh0IGRyYXcgY3Jvc3NlcyBtb3JlIGhvcHMgKGEgYFByb21pc2UucmFjZWAgcmVzb2x1dGlvbiwgYVxuICogdXNlci1sZXZlbCBzZW1hcGhvcmUsIGFuIGFzeW5jLWl0ZXJhdG9yIHJlYWQpIGNhbiBzdGlsbCBiZSBvdmVydGFrZW4gYnkgYVxuICogbGF0ZXItaW4tbG9nIGRlbGl2ZXJ5J3Mgc2hvcnRlciBjYXNjYWRlLCBzbyB0aGUgcnVuJ3MgZHJhdyBvcmRlciwgaW5jbHVkaW5nXG4gKiBpdHMgY29ycmVsYXRpb24gaWRzLCBkZXBlbmRzIG9uIGhvdyBtdWNoIGxvZyB0aGlzIHJlcGxheSBsb2FkZWQuXG4gKiBPbiwgdGhlIHlpZWxkIGJlY29tZXMgYSBmaXhwb2ludDogdGhlIGRlbGl2ZXJ5IHJlc29sdmVzIG9ubHkgb25jZSBldmVyeVxuICogZWFybGllciBjYXNjYWRlIGhhcyBxdWllc2NlZCwgbWFraW5nIHRoZSBkcmF3IHNlcXVlbmNlIGEgcHVyZSBmdW5jdGlvbiBvZlxuICogdGhlIGRlbnNlIGxvZywgc3RhYmxlIHVuZGVyIHByZWZpeCBleHRlbnNpb24sIGFuZCBjb25jdXJyZW50IHdyaXRlcnMnXG4gKiBkdXBsaWNhdGUgY3JlYXRlcyBpZGVudGljYWwgKGRlZHVwZWQpIGluc3RlYWQgb2YgY29sbGlkaW5nLlxuICovXG5mdW5jdGlvbiBpc0xvZ09yZGVyRHJhd3NFbmFibGVkKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gcHJvY2Vzcy5lbnYuV09SS0ZMT1dfTE9HX09SREVSX0RSQVdTICE9PSAnMCc7XG59XG5cbi8qKlxuICogT25lIHF1aWVzY2VuY2UgdHVybjogbGV0cyB0aGUgZW50aXJlIHBlbmRpbmcgbWljcm90YXNrIHF1ZXVlIGRyYWluLCB0aGVuXG4gKiB5aWVsZHMgdG8gdGhlIGV2ZW50IGxvb3Agb25jZS4gYHNldEltbWVkaWF0ZWAgKGNoZWNrIHBoYXNlKSBpcyB1c2VkIHdoZXJlXG4gKiBhdmFpbGFibGUgYmVjYXVzZSBOb2RlIGNsYW1wcyBgc2V0VGltZW91dCgwKWAgdG8gfjFtcyB3aGlsZSBgc2V0SW1tZWRpYXRlYFxuICogY29zdHMgfjIwwrVzLiBFdmVyeSBicmFuY2gtZGVjaWRpbmcgZGVsaXZlcnkgcGF5cyB0aGlzIHR1cm4gYXQgbGVhc3RcbiAqIG9uY2UsIHNvIG9uIGEgc2VxdWVudGlhbCByZXBsYXkgdGhlIGNsYW1wIGlzIHRoZSB3aG9sZSBjb3N0LiBUaW1lcnMgc3RpbGxcbiAqIHJ1biBiZXR3ZWVuIGNvbnNlY3V0aXZlIHR1cm5zICh0aGUgbG9vcCByZS1lbnRlcnMgdGhlIGV2ZW50IGxvb3AgZWFjaFxuICogaXRlcmF0aW9uLCBwYXNzaW5nIHRocm91Z2ggdGhlIHRpbWVycyBwaGFzZSksIHNvIGNoYWlucyBwYXJrZWQgb24gdGhlXG4gKiBzYWZldHktbmV0IGRpc3BlbnNlcidzIGBzZXRUaW1lb3V0YCBjYWRlbmNlIGFyZSBub3Qgc3RhcnZlZC5cbiAqL1xuZnVuY3Rpb24gcXVpZXNjZW5jZVR1cm4oZGVsYXlNczogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gIGlmIChkZWxheU1zID09PSAwICYmIHR5cGVvZiBzZXRJbW1lZGlhdGUgPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUpID0+IHNldEltbWVkaWF0ZShyZXNvbHZlKSk7XG4gIH1cbiAgcmV0dXJuIG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIGRlbGF5TXMpKTtcbn1cblxuLyoqXG4gKiBXYWl0cyB1bnRpbCB0aGUgd29ya2Zsb3cgY2FuIG1ha2Ugbm8gZnVydGhlciBwcm9ncmVzcyB3aXRob3V0IGFub3RoZXJcbiAqIGRlbGl2ZXJ5OiByZXBlYXRlZCAocHJvbWlzZS1xdWV1ZSBkcmFpbiArIGV2ZW50LWxvb3AgdHVybilzIHVudGlsIGEgZnVsbFxuICogdHVybiBwYXNzZXMgd2l0aCBubyBuZXcgVUxJRCBkcmF3cyBhbmQgbm8gaHlkcmF0aW9uIGluIGZsaWdodC5cbiAqXG4gKiBUZXJtaW5hdGlvbjogZWFjaCBleHRyYSBpdGVyYXRpb24gcmVxdWlyZXMgYSBuZXcgVUxJRCBkcmF3IG9yIGEgaHlkcmF0aW9uXG4gKiBzdGFydGVkIGluIHRoZSBwcmV2aW91cyB0dXJuLiBgbWludENvdW50YCBjb3VudHMgRVZFUlkgZHJhdyBmcm9tIHRoZSBydW4nc1xuICogc2VxdWVuY2UsIGluY2x1ZGluZyBjb3JyZWxhdGlvbiBpZHMgYW5kIHNlcmlhbGl6YXRpb24tZHJpdmVuIGRyYXdzIChzdHJlYW1cbiAqIGlkcyBtaW50ZWQgdGhyb3VnaCB0aGUgYFNUQUJMRV9VTElEYCBnbG9iYWwgd2hpbGUgZGVoeWRyYXRpbmcpLiBUaGlzIGlzXG4gKiBjb25zZXJ2YXRpdmUgaW4gdGhlIHNhZmUgZGlyZWN0aW9uOiBzZXJpYWxpemF0aW9uIGRyYXdzIG9ubHkgZXh0ZW5kIHRoZVxuICogd2FpdCwgYW5kIGJvdGggYm9keSBwcm9ncmVzcyBhbmQgdGhlIHNlcmlhbGl6YXRpb24gd29yayBvbmUgY2FzY2FkZSBjYW5cbiAqIHNjaGVkdWxlIGFyZSBmaW5pdGUgYmV0d2VlbiBkZWxpdmVyaWVzLCBzbyB0aGUgZml4cG9pbnQgaXMgcmVhY2hlZC4gVGhlXG4gKiBsb29wIGhvbGRzIHRoaXMgZGVsaXZlcnkncyBvd24gYmFycmllciByZWdpc3RlcmVkIChpdHMgYG1hcmtEZWxpdmVyZWRgIGhhc1xuICogbm90IHJ1biksIHNvIGBpc0RlbGl2ZXJ5SWRsZWAgc3RheXMgZmFsc2UgYW5kIG5vIHN1c3BlbnNpb24gY2FuIHByZWVtcHQgdGhlXG4gKiBjYXNjYWRlIGJlaW5nIHdhaXRlZCBvdXQuXG4gKlxuICogQSByZWplY3RlZCBgcHJvbWlzZVF1ZXVlYCBzZXR0bGVzIGltbWVkaWF0ZWx5IGFuZCBmb3JldmVyLCBzbyBsb29waW5nIGF0XG4gKiB0aGUgbm9ybWFsIGNhZGVuY2Ugb24gYSBmYWlsZWQgcnVuIHdvdWxkIGRlZ2VuZXJhdGUgaW50byBhIGJ1c3kgbG9vcCAodGhlXG4gKiBzYW1lIGhhemFyZCB7QGxpbmsgZW5zdXJlQmFycmllclNhZmV0eU5ldH0gZG9jdW1lbnRzKS4gSXRlcmF0aW9ucyB0aGF0XG4gKiBvYnNlcnZlIHRoZSBxdWV1ZSByZWplY3RlZCBiYWNrIG9mZiB0byBhIDUwbXMgdGljayBpbnN0ZWFkLlxuICovXG5hc3luYyBmdW5jdGlvbiBxdWllc2NlRWFybGllckNhc2NhZGVzKFxuICBjdHg6IFdvcmtmbG93T3JjaGVzdHJhdG9yQ29udGV4dCxcbiAgZXZlbnRJbmRleDogbnVtYmVyXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgZm9yICg7Oykge1xuICAgIGNvbnN0IG1pbnRzQmVmb3JlID0gY3R4Lm1pbnRDb3VudCA/PyAwO1xuICAgIGNvbnN0IHBlbmRpbmdCZWZvcmUgPSBjdHgucGVuZGluZ0RlbGl2ZXJpZXM7XG4gICAgLy8gU2V0dGxlZCBvciByZWplY3RlZCwgdGhlIHF1ZXVlIHNuYXBzaG90IG9ubHkgb3JkZXJzIHVzIGJlaGluZCB3b3JrXG4gICAgLy8gYWxyZWFkeSBjaGFpbmVkOyBhIHJlamVjdGlvbiBpcyB0aGUgcnVuIGZhaWxpbmcgZWxzZXdoZXJlLlxuICAgIGNvbnN0IHF1ZXVlUmVqZWN0ZWQgPSBhd2FpdCBjdHgucHJvbWlzZVF1ZXVlLnRoZW4oXG4gICAgICAoKSA9PiBmYWxzZSxcbiAgICAgICgpID0+IHRydWVcbiAgICApO1xuICAgIGF3YWl0IHF1aWVzY2VuY2VUdXJuKHF1ZXVlUmVqZWN0ZWQgPyA1MCA6IDApO1xuICAgIGlmIChcbiAgICAgIChjdHgubWludENvdW50ID8/IDApICE9PSBtaW50c0JlZm9yZSB8fFxuICAgICAgcGVuZGluZ0JlZm9yZSAhPT0gMCB8fFxuICAgICAgY3R4LnBlbmRpbmdEZWxpdmVyaWVzICE9PSAwXG4gICAgKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgLy8gUXVpZXQgaXMgbm90IGVub3VnaCBvbiBpdHMgb3duOiBzZXZlcmFsIGRlbGl2ZXJ5IGNoYWlucyBjYW4gYmUgc2l0dGluZ1xuICAgIC8vIGluIHRoaXMgbG9vcCBhdCBvbmNlLCBhbmQgbGV0dGluZyB0aGUgZmlyc3QgcXVpZXQgb2JzZXJ2YXRpb24gcmVzb2x2ZVxuICAgIC8vIHdvdWxkIGJyZWFrIHRoZSB0aWUgYnkgdGltZXIgYXJyaXZhbC4gVGhpcyBtb2RlIHJlbW92ZXMgdGhhdCBhcnJpdmFsLW9yZGVyXG4gICAgLy8gZGVwZW5kZW5jZS4gQSBsb3dlci1pbmRleCBBUk1FRCBiYXJyaWVyIGlzIGEgZGVsaXZlcnkgY29tbWl0dGVkIHRvXG4gICAgLy8gaGFwcGVuaW5nIHRoYXQgaGFzIG5vdCBoYXBwZW5lZCB5ZXQsIHNvIHRoaXMgb25lIGtlZXBzIHdhaXRpbmcuIFVuYXJtZWRcbiAgICAvLyBlbnRyaWVzIChidWZmZXJlZCBwYXlsb2FkcyBub2JvZHkgaGFzIGNsYWltZWQpIGRvIG5vdCBibG9jaywgZXhhY3RseSBhc1xuICAgIC8vIGluIGBnYXRlc09uYDogdGhlaXIgaGFuZG92ZXIgaXMgY2xhaW0tZHJpdmVuLCB3aGljaCBpcyBib2R5LXBvc2l0aW9uXG4gICAgLy8gZGV0ZXJtaW5lZCBhbmQgdGhlcmVmb3JlIGFscmVhZHkgYSBmdW5jdGlvbiBvZiB0aGUgcHJlZml4LlxuICAgIC8vXG4gICAgLy8gVGhpcyBpcyBkZWxpYmVyYXRlbHkgYSBXSURFUiB3YWl0cy1mb3IgcmVsYXRpb24gdGhhbiBgZ2F0ZXNPbmAgKHdoaWNoLFxuICAgIC8vIGUuZy4sIGV4Y2x1ZGVzIHdhaXTihpJ3YWl0KTogdW5kZXIgbG9nLW9yZGVyIGRyYXdzIEVWRVJZIGJyYW5jaC1kZWNpZGluZ1xuICAgIC8vIGRlbGl2ZXJ5IG11c3QgcmVzb2x2ZSBpbiBsb2cgb3JkZXIsIGtpbmRzIGluY2x1ZGVkLiBUaGUgd2lkdGggaXMgc2FmZVxuICAgIC8vIGFnYWluc3QgdGhlIGRpc3BlbnNlciBkZWFkbG9jayB0aGF0IGByZXNvbHZlc09uSXRzT3duYCBndWFyZHMsIGJlY2F1c2VcbiAgICAvLyB0aGUgb25lIGVkZ2UgdGhlIHdpZGVyIHJlbGF0aW9uIGFkZHMgKHdhaXRpbmcgb24gYW4gYXJtZWQgZW50cnkgdGhhdFxuICAgIC8vIGdhdGVzT24gZG9lcyBub3QgbW9kZWwpIGFsd2F5cyBib3R0b21zIG91dCBhdCB0aGUgc2FtZSB1bmFybWVkIHBheWxvYWQ6XG4gICAgLy8gYSBsb3dlciBhcm1lZCBXQUlUIGlzIG5vbi1zZWxmLXJlc29sdmluZyBvbmx5IHdoZW4gaXQgaXMgKHRyYW5zaXRpdmVseSlcbiAgICAvLyBwYXJrZWQgYmVoaW5kIGFuIHVuY2xhaW1lZCBidWZmZXJlZCBwYXlsb2FkLCBhbmQgYSB3YWl0IGdhdGVzIG9uIGV2ZXJ5XG4gICAgLy8gbG93ZXIgaG9vayBhbmQgc3RlcCBkaXJlY3RseSwgc28gdGhlIHNwaW5uZXIgaGVyZSBhbHNvIGdhdGVzIG9uIHRoYXRcbiAgICAvLyBwYXlsb2FkIHRocm91Z2ggYGdhdGVzT25gIGFuZCBpcyBpdHNlbGYgcmVwb3J0ZWQgbm9uLXNlbGYtcmVzb2x2aW5nLlxuICAgIC8vIFRoZSBkaXNwZW5zZXIgdGhlcmVmb3JlIHN0YXlzIHVuYmxvY2tlZCBhbmQgcmV0aXJlcyB0aGUgY2hhaW4gaGVhZDsgc2VlXG4gICAgLy8gdGhlIHBhcmtlZC1jaGFpbiB0ZXN0IGluIGRlbGl2ZXJ5LWJhcnJpZXItY292ZXJhZ2UudGVzdC50cy5cbiAgICBsZXQgbG93ZXJBcm1lZCA9IGZhbHNlO1xuICAgIGZvciAoY29uc3QgW2luZGV4LCBlbnRyeV0gb2YgY3R4LnBlbmRpbmdEZWxpdmVyeUJhcnJpZXJzID8/IFtdKSB7XG4gICAgICBpZiAoaW5kZXggPCBldmVudEluZGV4ICYmIGVudHJ5LmFybWVkKSB7XG4gICAgICAgIGxvd2VyQXJtZWQgPSB0cnVlO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKCFsb3dlckFybWVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBhd2FpdEVhcmxpZXJEZWxpdmVyaWVzKFxuICBjdHg6IFdvcmtmbG93T3JjaGVzdHJhdG9yQ29udGV4dCxcbiAgZXZlbnRJbmRleDogbnVtYmVyIHwgdW5kZWZpbmVkLFxuICBraW5kOiBEZWxpdmVyeUtpbmRcbik6IFByb21pc2U8dm9pZD4ge1xuICAvLyBEZWZlbnNpdmU6IHRvbGVyYXRlIGNvbnRleHRzIHRoYXQgcHJlZGF0ZSB0aGlzIGZpZWxkICh0ZXN0IGhhcm5lc3NlcykuXG4gIGlmIChldmVudEluZGV4ID09PSB1bmRlZmluZWQgfHwgIWN0eC5wZW5kaW5nRGVsaXZlcnlCYXJyaWVycykge1xuICAgIHJldHVybjtcbiAgfVxuICBjb25zdCBiYXJyaWVycyA9IGN0eC5wZW5kaW5nRGVsaXZlcnlCYXJyaWVycztcbiAgY29uc3QgZWFybGllcjogUHJvbWlzZTx2b2lkPltdID0gW107XG4gIGZvciAoY29uc3QgW2luZGV4LCBlbnRyeV0gb2YgYmFycmllcnMpIHtcbiAgICBpZiAoIWdhdGVzT24oa2luZCwgZXZlbnRJbmRleCwgaW5kZXgsIGVudHJ5KSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGVhcmxpZXIucHVzaChlbnRyeS5yZWxlYXNlZCk7XG4gIH1cbiAgaWYgKGVhcmxpZXIubGVuZ3RoID4gMCkge1xuICAgIGF3YWl0IFByb21pc2UuYWxsKGVhcmxpZXIpO1xuICB9XG4gIGlmIChpc0xvZ09yZGVyRHJhd3NFbmFibGVkKCkpIHtcbiAgICAvLyBVbmNvbmRpdGlvbmFsLCBub3QganVzdCB3aGVuIGEgYmFycmllciB3YXMgc3RpbGwgcmVnaXN0ZXJlZDogYW4gZWFybGllclxuICAgIC8vIGRlbGl2ZXJ5J3MgYmFycmllciBkZXJlZ2lzdGVycyB3aGVuIGl0cyByZXNvbHZlKCkgcnVucywgYnV0IHRoZSBicmFuY2hcbiAgICAvLyBpdCB3b2tlIG1heSBzdGlsbCBiZSBob3BzIGF3YXkgZnJvbSBpdHMgbmV4dCBkcmF3LiBBIGxhdGVyIGRlbGl2ZXJ5XG4gICAgLy8gY29uc3VtZWQgYWZ0ZXIgdGhhdCBkZXJlZ2lzdHJhdGlvbiBzZWVzIGFuIGVtcHR5IGdhdGUgc2V0LCBhbmQgd2l0aG91dFxuICAgIC8vIHRoaXMgaXQgd291bGQgcmVzb2x2ZSBtaWQtY2FzY2FkZSBhbmQgb3ZlcnRha2UgdGhlIGRyYXcuIFRoaXMgaXMgdGhlIGV4YWN0XG4gICAgLy8gYXJyaXZhbC1vcmRlciBkZXBlbmRlbmNlIHRoaXMgbW9kZSBleGlzdHMgdG8gcmVtb3ZlLiBDb3N0cyBvbmUgcXVpZXRcbiAgICAvLyBtYWNyb3Rhc2sgdHVybiB3aGVuIG5vdGhpbmcgaXMgaW4gZmxpZ2h0LlxuICAgIGF3YWl0IHF1aWVzY2VFYXJsaWVyQ2FzY2FkZXMoY3R4LCBldmVudEluZGV4KTtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKGVhcmxpZXIubGVuZ3RoID4gMCkge1xuICAgIC8vIEFuIGVhcmxpZXIgZGVsaXZlcnkgYmVpbmcgXCJkZWxpdmVyZWRcIiBvbmx5IG1lYW5zIGl0cyBgcmVzb2x2ZSgpYCByYW4uXG4gICAgLy8gVGhlIGJyYW5jaCBpdCB3b2tlIG1heSBuZWVkIGFuIGFyYml0cmFyeSBudW1iZXIgb2YgZnVydGhlciBtaWNyb3Rhc2tcbiAgICAvLyBob3BzIGJlZm9yZSBpdCByZWFjaGVzIGl0cyBuZXh0IGB1c2VTdGVwYCBjYWxsIGFuZCBkcmF3cyBhIFVMSUQ6IGFcbiAgICAvLyBgZm9yIGF3YWl0YCBvdmVyIGEgaG9vaywgZm9yIGluc3RhbmNlLCByZXN1bWVzIHRoZSBnZW5lcmF0b3IsIHNldHRsZXNcbiAgICAvLyB0aGUgcHJvbWlzZSBmcm9tIGBuZXh0KClgLCBhbmQgb25seSB0aGVuIHJ1bnMgdGhlIGxvb3AgYm9keS4gUmVzb2x2aW5nXG4gICAgLy8gdGhpcyBkZWxpdmVyeSBvbiBhIG1pY3JvdGFzayB3b3VsZCBsZXQgaXQgb3ZlcnRha2UgdGhhdCBicmFuY2ggYW5kXG4gICAgLy8gcmVvcmRlciB0aGUgVUxJRCBhbGxvY2F0aW9uIGFueXdheSwgdHVybmluZyB0aGUgZ3VhcmFudGVlIGJlbG93IGludG8gYVxuICAgIC8vIGhvcC1jb3VudCByYWNlIHRoYXQgaG9sZHMgb25seSBmb3IgdGhlIHNob3J0ZXN0IGNvbnN1bWVycy5cbiAgICAvL1xuICAgIC8vIFlpZWxkaW5nIGEgbWFjcm90YXNrIGxldHMgdGhlIGVhcmxpZXIgYnJhbmNoJ3MgZW50aXJlIG1pY3JvdGFzayBjaGFpblxuICAgIC8vIGRyYWluIGZpcnN0LCB3aGF0ZXZlciBpdHMgbGVuZ3RoLCBzbyBsb2cgb3JkZXIgc3Vydml2ZXMgcmVnYXJkbGVzcyBvZlxuICAgIC8vIGhvdyB0aGUgd29ya2Zsb3cgY29uc3VtZXMgdGhlIGVhcmxpZXIgZGVsaXZlcnkuIE9ubHkgZGVsaXZlcmllcyB0aGF0XG4gICAgLy8gYWN0dWFsbHkgaGFkIHRvIGRlZmVyIHBheSB0aGlzLCBzbyB0aGUgY29tbW9uIHNpbmdsZS1kZWxpdmVyeSBkcmFpbiBpc1xuICAgIC8vIHVuYWZmZWN0ZWQuXG4gICAgYXdhaXQgbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgMCkpO1xuICB9XG59XG5cbi8qKiBIYW5kbGUgZm9yIGEgcmVnaXN0ZXJlZCBicmFuY2gtZGVjaWRpbmcgZGVsaXZlcnkgYmFycmllci4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGVsaXZlcnlCYXJyaWVyIHtcbiAgLyoqXG4gICAqIE1hcmsgdGhpcyBkZWxpdmVyeSBhcyBkZWxpdmVyZWQgdG8gdGhlIHdvcmtmbG93LiBSZXNvbHZlcyBpdHNcbiAgICogYHJlbGVhc2VkYCBwcm9taXNlIHNvIGFueSBsYXRlci1pbi1sb2cgZGVsaXZlcnkgZ2F0ZWQgb24gaXQgKHZpYVxuICAgKiB7QGxpbmsgYXdhaXRFYXJsaWVyRGVsaXZlcmllc30pIG1heSBwcm9jZWVkLCBhbmQgcmVtb3ZlcyBpdCBmcm9tIHRoZVxuICAgKiByZWdpc3RyeS4gSWRlbXBvdGVudC5cbiAgICovXG4gIG1hcmtEZWxpdmVyZWQ6ICgpID0+IHZvaWQ7XG4gIC8qKlxuICAgKiBNYXJrIHRoaXMgZGVsaXZlcnkgYXMgY29tbWl0dGVkIHRvIGhhcHBlbmluZywgZm9yIGEgYmFycmllciByZWdpc3RlcmVkXG4gICAqIHVuYXJtZWQgKGEgYnVmZmVyZWQgaG9vayBwYXlsb2FkKSBvbmNlIGEgY29uc3VtZXIgaGFzIGNsYWltZWQgaXQuIEZyb21cbiAgICogdGhlbiBvbiBhIGxhdGVyIHN0ZXAgcmVzdWx0IG1heSBiZSBvcmRlcmVkIGJlaGluZCBpdC4gSWRlbXBvdGVudC5cbiAgICovXG4gIGFybTogKCkgPT4gdm9pZDtcbn1cblxuLyoqXG4gKiBSZWdpc3RlciBhIGJyYW5jaC1kZWNpZGluZyBkZWxpdmVyeSBhdCBpdHMgZXZlbnQtbG9nIGluZGV4IHNvIHRoYXQgbGF0ZXJcbiAqIGRlbGl2ZXJpZXMgY2FuIGJlIG9yZGVyZWQgc3RyaWN0bHkgYWZ0ZXIgaXQuIFJldHVybnMgYW4gaW5lcnQgaGFuZGxlIHdoZW5cbiAqIGBwZW5kaW5nRGVsaXZlcnlCYXJyaWVyc2AgaXMgbm90IGluaXRpYWxpemVkLlxuICpcbiAqIFBhc3MgYGFybWVkOiBmYWxzZWAgZm9yIGEgZGVsaXZlcnkgd2hvc2UgcmVzb2x1dGlvbiB3YWl0cyBvbiB3b3JrZmxvdyBjb2RlXG4gKiBhc2tpbmcgZm9yIGl0IChhIGJ1ZmZlcmVkIGhvb2sgcGF5bG9hZCk7IGNhbGwgYGFybSgpYCB3aGVuIGl0IGRvZXMuXG4gKlxuICogVG8gZ3VhcmFudGVlIGEgbGF0ZXIgZGVsaXZlcnkgZ2F0ZWQgb24gdGhpcyBvbmUgY2FuIG5ldmVyIGhhbmcgd2hlbiB0aGlzXG4gKiBkZWxpdmVyeSBpcyBhYmFuZG9uZWQgKHRoZSB3b3JrZmxvdyB0b29rIGEgZGlmZmVyZW50IGJyYW5jaCBvciBpc1xuICogc3VzcGVuZGluZyBhbmQgbmV2ZXIgb2JzZXJ2ZXMgaXQpLCB0aGUgYmFycmllciBhdXRvLXJlc29sdmVzIGF0IGlkbGUuXG4gKlxuICogSU5WQVJJQU5UIHJlcXVpcmVkIG9mIGV2ZXJ5IGNhbGwgc2l0ZTogYSBiYXJyaWVyIHRoYXQgaXMgZXZlciBgYXJtZWRgIG11c3RcbiAqIGJlIHBhaXJlZCB3aXRoIGEgZGVsaXZlcnkgY2hhaW4gdGhhdCBydW5zIHVuY29uZGl0aW9uYWxseSwgYXR0YWNoZWQgd2hlblxuICogdGhlIGV2ZW50IGlzIGNvbnN1bWVkICh3YWl0cywgc3RlcCByZXN1bHRzLCB3YWl0aW5nLWNvbnN1bWVyIGhvb2sgcGF5bG9hZHMsXG4gKiBhYm9ydHMpLCBvciBieSB0aGUgYGNsYWltKClgIHdob3NlIGludm9jYXRpb24gaXMgd2hhdCBhcm1zIGl0IChidWZmZXJlZFxuICogaG9vayBwYXlsb2FkcykuIFRoZSBpZGxlIGNoZWNrICh7QGxpbmsgc2NoZWR1bGVXaGVuSWRsZX0pIHJlZnVzZXMgdG9cbiAqIG9ic2VydmUgaWRsZSB3aGlsZSBhbiBhcm1lZCwgc2VsZi1yZXNvbHZpbmcgYmFycmllciBpcyB1bmRlbGl2ZXJlZCwgYW5kIHRoZVxuICogc2FmZXR5IG5ldCBiZWxvdyBpcyBpdHNlbGYgaWRsZS1nYXRlZCwgc28gYW4gYXJtZWQgYmFycmllciB3aXRoIG5vXG4gKiB1bmNvbmRpdGlvbmFsIGNoYWluIHdvdWxkIGxpdmVsb2NrIGV2ZXJ5IGlkbGUgY2hlY2sgaW4gdGhlIHJ1biwgaW5jbHVkaW5nXG4gKiBpdHMgb3duIHJldGlyZW1lbnQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWdpc3RlckRlbGl2ZXJ5QmFycmllcihcbiAgY3R4OiBXb3JrZmxvd09yY2hlc3RyYXRvckNvbnRleHQsXG4gIGV2ZW50SW5kZXg6IG51bWJlciB8IHVuZGVmaW5lZCxcbiAga2luZDogRGVsaXZlcnlLaW5kLFxuICBvcHRpb25zOiB7IGFybWVkPzogYm9vbGVhbiB9ID0ge31cbik6IERlbGl2ZXJ5QmFycmllciB7XG4gIGNvbnN0IGJhcnJpZXJzID0gY3R4LnBlbmRpbmdEZWxpdmVyeUJhcnJpZXJzO1xuICBpZiAoIWJhcnJpZXJzIHx8IGV2ZW50SW5kZXggPT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiB7IG1hcmtEZWxpdmVyZWQ6ICgpID0+IHt9LCBhcm06ICgpID0+IHt9IH07XG4gIH1cblxuICBjb25zdCBpbnN0YWxsID0gKGFybWVkOiBib29sZWFuKTogRGVsaXZlcnlCYXJyaWVyRW50cnkgPT4ge1xuICAgIGlmIChiYXJyaWVycy5oYXMoZXZlbnRJbmRleCkpIHtcbiAgICAgIHRocm93IG5ldyBXb3JrZmxvd1J1bnRpbWVFcnJvcihcbiAgICAgICAgYERlbGl2ZXJ5IGJhcnJpZXIgYWxyZWFkeSByZWdpc3RlcmVkIGF0IGV2ZW50IGluZGV4ICR7ZXZlbnRJbmRleH1gXG4gICAgICApO1xuICAgIH1cbiAgICBjb25zdCB7IHByb21pc2UsIHJlc29sdmUgfSA9IHdpdGhSZXNvbHZlcnM8dm9pZD4oKTtcbiAgICBjb25zdCBlbnRyeTogRGVsaXZlcnlCYXJyaWVyRW50cnkgPSB7XG4gICAgICBraW5kLFxuICAgICAgcmVsZWFzZWQ6IHByb21pc2UsXG4gICAgICBhcm1lZCxcbiAgICAgIHJldGlyZWQ6IGZhbHNlLFxuICAgICAgcmV0aXJlOiAoKSA9PiB7XG4gICAgICAgIGlmIChlbnRyeS5yZXRpcmVkKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGVudHJ5LnJldGlyZWQgPSB0cnVlO1xuICAgICAgICBpZiAoYmFycmllcnMuZ2V0KGV2ZW50SW5kZXgpID09PSBlbnRyeSkge1xuICAgICAgICAgIGJhcnJpZXJzLmRlbGV0ZShldmVudEluZGV4KTtcbiAgICAgICAgfVxuICAgICAgICByZXNvbHZlKCk7XG4gICAgICB9LFxuICAgIH07XG4gICAgYmFycmllcnMuc2V0KGV2ZW50SW5kZXgsIGVudHJ5KTtcblxuICAgIC8vIFNhZmV0eSBuZXQ6IGlmIHRoaXMgZGVsaXZlcnkgaXMgbmV2ZXIgZGVsaXZlcmVkIHRvIHRoZSB3b3JrZmxvdyAoaXRzXG4gICAgLy8gYnJhbmNoIHdhcyBub3QgdGFrZW4gLyB0aGUgcnVuIGlzIHN1c3BlbmRpbmcsIG9yIGEgYnVmZmVyZWQgaG9vayBwYXlsb2FkXG4gICAgLy8gaXMgb25seSBjbGFpbWVkIGFmdGVyIGEgbGF0ZXIgZGVsaXZlcnkgdGhlIHdvcmtmbG93IGlzIHN0aWxsIHdhaXRpbmdcbiAgICAvLyBvbiksIGl0IGlzIHJldGlyZWQgYXQgaWRsZSBzbyBhIGxhdGVyIGRlbGl2ZXJ5IGdhdGVkIG9uIGl0IGNhbm5vdFxuICAgIC8vIGRlYWRsb2NrIGFuZCB0aGUgcmVnaXN0cnkgY2Fubm90IGxlYWsgYW4gZW50cnkgcGVyIGFiYW5kb25lZCBkZWxpdmVyeS5cbiAgICAvLyBSZXRpcmVtZW50IGdvZXMgdGhyb3VnaCB0aGUgY29udGV4dCdzIHNpbmdsZSBvcmRlcmVkIGRpc3BlbnNlciByYXRoZXJcbiAgICAvLyB0aGFuIGEgcGVyLWJhcnJpZXIgaWRsZSBwb2xsLiBTZWUge0BsaW5rIGVuc3VyZUJhcnJpZXJTYWZldHlOZXR9IGZvciB3aHlcbiAgICAvLyB0aGUgT1JERVIgb2YgdGhlc2UgcmV0aXJlbWVudHMgaXMgbG9hZC1iZWFyaW5nLlxuICAgIGVuc3VyZUJhcnJpZXJTYWZldHlOZXQoY3R4KTtcbiAgICByZXR1cm4gZW50cnk7XG4gIH07XG5cbiAgbGV0IGVudHJ5ID0gaW5zdGFsbChvcHRpb25zLmFybWVkID8/IHRydWUpO1xuICBsZXQgZGVsaXZlcmVkVG9Xb3JrZmxvdyA9IGZhbHNlO1xuXG4gIHJldHVybiB7XG4gICAgbWFya0RlbGl2ZXJlZDogKCkgPT4ge1xuICAgICAgaWYgKGRlbGl2ZXJlZFRvV29ya2Zsb3cpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgZGVsaXZlcmVkVG9Xb3JrZmxvdyA9IHRydWU7XG4gICAgICBlbnRyeS5yZXRpcmUoKTtcbiAgICB9LFxuICAgIGFybTogKCkgPT4ge1xuICAgICAgaWYgKGRlbGl2ZXJlZFRvV29ya2Zsb3cpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgLy8gVGhlIGlkbGUgc2FmZXR5IG5ldCBtYXkgcmV0aXJlIGFuIHVuY2xhaW1lZCBidWZmZXJlZCBob29rIHBheWxvYWRcbiAgICAgIC8vIHdoaWxlIGEgcmV0YWluZWQgVk0ga2VlcHMgaXRzIGBjbGFpbSgpYCBjbG9zdXJlIGFsaXZlLiBJZiB3b3JrZmxvd1xuICAgICAgLy8gY29kZSBsYXRlciBjbGFpbXMgdGhhdCBwYXlsb2FkLCByZXBsYWNlIHRoZSBzZXR0bGVkIGVudHJ5IHNvIGRlbGl2ZXJ5XG4gICAgICAvLyByZW1haW5zIG5vbi1pZGxlIHVudGlsIHRoZSBjbGFpbSByZWFjaGVzIHRoZSB3b3JrZmxvdy5cbiAgICAgIGlmIChlbnRyeS5yZXRpcmVkKSB7XG4gICAgICAgIGVudHJ5ID0gaW5zdGFsbCh0cnVlKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKGJhcnJpZXJzLmdldChldmVudEluZGV4KSAhPT0gZW50cnkpIHtcbiAgICAgICAgdGhyb3cgbmV3IFdvcmtmbG93UnVudGltZUVycm9yKFxuICAgICAgICAgIGBEZWxpdmVyeSBiYXJyaWVyIGxvc3Qgb3duZXJzaGlwIG9mIGV2ZW50IGluZGV4ICR7ZXZlbnRJbmRleH1gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBlbnRyeS5hcm1lZCA9IHRydWU7XG4gICAgfSxcbiAgfTtcbn1cblxuLyoqXG4gKiBDb250ZXh0cyB3aG9zZSBiYXJyaWVyIHNhZmV0eS1uZXQgZGlzcGVuc2VyIGlzIGN1cnJlbnRseSBhcm1lZC4gTW9kdWxlLWxldmVsXG4gKiBzbyB0aGUgY29udGV4dCBpbnRlcmZhY2UgKGNvbnN0cnVjdGVkIGxpdGVyYWxseSBieSBtYW55IHRlc3QgaGFybmVzc2VzKVxuICogbmVlZHMgbm8gbmV3IGZpZWxkOyBlbnRyaWVzIGRyb3Agd2l0aCB0aGUgY29udGV4dC5cbiAqL1xuLy8gcGVyLWNvcHktb2s6IGtleWVkIG9uIHRoZSBvcmNoZXN0cmF0b3IgY29udGV4dCBvYmplY3QsIGFuZCBhIGNvbnRleHQgaXMgYXJtZWRcbi8vIGFuZCBvYnNlcnZlZCBieSB0aGUgc2FtZSBjb3B5IHRoYXQgY3JlYXRlZCBpdC4gRW50cmllcyBjYW4gbmV2ZXIgYmUgbG9va2VkIHVwXG4vLyBmcm9tIGFub3RoZXIgY29weSBiZWNhdXNlIHRoYXQgY29weSBoYXMgbm8gcmVmZXJlbmNlIHRvIHRoZSBrZXkuXG5jb25zdCBhY3RpdmVCYXJyaWVyU2FmZXR5TmV0cyA9IG5ldyBXZWFrU2V0PFdvcmtmbG93T3JjaGVzdHJhdG9yQ29udGV4dD4oKTtcblxuLyoqXG4gKiBUaGUgYmFycmllciByZWdpc3RyeSdzIHNhZmV0eSBuZXQ6IE9ORSBpZGxlLWdhdGVkIGRpc3BlbnNlciBwZXIgY29udGV4dCB0aGF0XG4gKiByZXRpcmVzLCBhdCBlYWNoIG9ic2VydmF0aW9uIG9mIGRlbGl2ZXJ5IGlkbGUsIG9ubHkgdGhlIExPV0VTVC1pbmRleCBlbnRyeVxuICogc3RpbGwgcmVnaXN0ZXJlZCwgdGhlbiB5aWVsZHMgc28gdGhlIGNoYWluIGl0IHJlbGVhc2VkIGNhbiBydW4gYmVmb3JlIHRoZVxuICogbmV4dCByZXRpcmVtZW50IGlzIGNvbnNpZGVyZWQuXG4gKlxuICogV2h5IG9uZSBvcmRlcmVkIGRpc3BlbnNlciBhbmQgbm90IGEgcG9sbCBwZXIgYmFycmllciAod2hpY2ggaXMgd2hhdCB0aGlzXG4gKiByZXBsYWNlZCk6IHRoZSBvcmRlciBvZiBzYWZldHktbmV0IHJldGlyZW1lbnRzIGRlY2lkZXMgdGhlIGRlbGl2ZXJ5IG9yZGVyIG9mXG4gKiBldmVyeSBjaGFpbiBwYXJrZWQgYmVoaW5kIGFuIHVuY2xhaW1lZCBidWZmZXJlZCBob29rIHBheWxvYWQ6IGEgaG9vayB0aGVcbiAqIHdvcmtmbG93IG5ldmVyIHJlYWRzIChhIGZpcmUtYW5kLWZvcmdldCBgY3JlYXRlSG9va2ApIHBhcmtzIGV2ZXJ5IGxhdGVyXG4gKiBhcm1lZCB3YWl0L2hvb2sgYmVoaW5kIGEgYmFycmllciB0aGF0IG9ubHkgdGhpcyBuZXQgY2FuIHJldGlyZS4gUGVyLWJhcnJpZXJcbiAqIHBvbGxzIGZpcmUgaW4gd2hhdGV2ZXIgb3JkZXIgdGhlaXIgcmUtYXJtIGN5Y2xlcyBsYW5kLCBhbmQgZWFjaCByZS1hcm1cbiAqIGF0dGFjaGVzIHRvIGEgYHByb21pc2VRdWV1ZWAgdGhhdCBncm93cyBiZXR3ZWVuIGNoZWNrcywgc28gd2l0aCBzZXZlcmFsXG4gKiBwYXJrZWQgc2VnbWVudHMgdGhlIHJlbGVhc2Ugb3JkZXIgZGVjYXlzIHRvIHRpbWluZyBub2lzZS4gRHJhd3MgKGB1c2VTdGVwYFxuICogY29ycmVsYXRpb24gaWRzKSB0aGVuIGRlcGVuZCBvbiB3aGljaCBzZWdtZW50IGhhcHBlbmVkIHRvIHJlbGVhc2UgZmlyc3Q6XG4gKiBjb25jcmV0ZWx5LCBvbiBob3cgTVVDSCBsb2cgdGhlIHJlcGxheSBsb2FkZWQsIHNpbmNlIHRoYXQgZGVjaWRlcyB3aGF0IGlzIGluXG4gKiB0aGUgcmVnaXN0cnkuIFRoYXQgaXMgdGhlIG1lY2hhbmlzbSBiZWhpbmQgc2xvdC1tb2RlIENPUlJVUFRFRF9FVkVOVF9MT0cgb25cbiAqIHN0b3JtLXNoYXBlZCBydW5zIChzZWUgc3Rvcm0tbG9nLXJlcGxheS50ZXN0LnRzLCBidWlsdCBmcm9tIGEgcHJvZHVjdGlvblxuICogbG9nKTogdHdvIHJlcGxheXMgb2YgdGhlIHNhbWUgcnVuIGhvbGRpbmcgZGlmZmVyZW50LWxlbmd0aCBwcmVmaXhlcyBib3VuZFxuICogdGhlIHNhbWUgY29ycmVsYXRpb24gb3JkaW5hbCB0byBkaWZmZXJlbnQgc3RlcHMuXG4gKlxuICogUmV0aXJpbmcgbG93ZXN0LWZpcnN0IGlzIG5vdCBtZXJlbHkgdGlkeSwgaXQgaXMgdGhlIG9ubHkgb3JkZXIgdGhhdCBjYW5ub3RcbiAqIGludmVydCB0aGUgbG9nOiBldmVyeSBnYXRlIHBvaW50cyBmcm9tIGEgaGlnaGVyIGluZGV4IHRvIGEgc3RyaWN0bHkgbG93ZXJcbiAqIG9uZSwgc28gYXQgZGVsaXZlcnkgaWRsZSB0aGUgbG93ZXN0IHVuZGVsaXZlcmVkIGVudHJ5IGdhdGVzIG9uIG5vdGhpbmdcbiAqIHN0aWxsIHJlZ2lzdGVyZWQ6IGl0IGlzIHRoZSBoZWFkIG9mIGV2ZXJ5IHBhcmtlZCBjaGFpbiAoaW4gcHJhY3RpY2UsIHRoZVxuICogdW5jbGFpbWVkIHBheWxvYWQgaXRzZWxmKS4gUmVsZWFzaW5nIGl0IGxldHMgdGhlIGNoYWluIGFib3ZlIGRlbGl2ZXJcbiAqIHRocm91Z2ggdGhlIG9yZGluYXJ5IGJhcnJpZXIgb3JkZXI7IGFueXRoaW5nIHRoZSByZWxlYXNlIHdha2VzIGZsaXBzXG4gKiB7QGxpbmsgaGFzUGFya2VkQ29tbWl0dGVkRGVsaXZlcnl9IGJhY2sgdG8gdHJ1ZSwgd2hpY2ggcmUtYmxvY2tzIHRoaXNcbiAqIGRpc3BlbnNlciB1bnRpbCB0aGUgY2hhaW4gaGFzIGZ1bGx5IGRyYWluZWQuIEEgaGlnaGVyIGVudHJ5IG11c3QgbmV2ZXIgYmVcbiAqIHJldGlyZWQgd2hpbGUgYSBsb3dlciBvbmUgaXMgcmVnaXN0ZXJlZCwgd2hpY2ggaXMgZXhhY3RseSB0aGUgaW52ZXJzaW9uXG4gKiBkZXNjcmliZWQgb24ge0BsaW5rIGF3YWl0RWFybGllckRlbGl2ZXJpZXN9LlxuICpcbiAqIFRoZSBkaXNwZW5zZXIgZ29lcyBkb3JtYW50IHdoZW4gdGhlIHJlZ2lzdHJ5IGVtcHRpZXMgYW5kIGlzIHJlLWFybWVkIGJ5IHRoZVxuICogbmV4dCByZWdpc3RyYXRpb24sIHNvIGFuIGlkbGUgY29udGV4dCBob2xkcyBubyBsaXZlIHRpbWVyLlxuICovXG5mdW5jdGlvbiBlbnN1cmVCYXJyaWVyU2FmZXR5TmV0KGN0eDogV29ya2Zsb3dPcmNoZXN0cmF0b3JDb250ZXh0KTogdm9pZCB7XG4gIGNvbnN0IGJhcnJpZXJzID0gY3R4LnBlbmRpbmdEZWxpdmVyeUJhcnJpZXJzO1xuICBpZiAoIWJhcnJpZXJzIHx8IGFjdGl2ZUJhcnJpZXJTYWZldHlOZXRzLmhhcyhjdHgpKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGFjdGl2ZUJhcnJpZXJTYWZldHlOZXRzLmFkZChjdHgpO1xuICBjb25zdCByZWFybSA9ICgpID0+IHtcbiAgICBzZXRUaW1lb3V0KGNoZWNrLCAwKTtcbiAgfTtcbiAgLy8gQSByZWplY3RlZCBwcm9taXNlUXVldWUgc2V0dGxlcyBpbW1lZGlhdGVseSBhbmQgZm9yZXZlciwgc28gcmUtYXJtaW5nXG4gIC8vIHRocm91Z2ggaXQgYXQgdGhlIG5vcm1hbCBjYWRlbmNlIHdvdWxkIGRlZ2VuZXJhdGUgaW50byBhIGJ1c3kgbG9vcCBvbiBhblxuICAvLyBhYmFuZG9uZWQgY29udGV4dC4gQmFjayBvZmYgaW5zdGVhZDogY29ycmVjdG5lc3Mgb25seSBuZWVkcyB0aGUgZGlzcGVuc2VyXG4gIC8vIHRvIHN0aWxsIGV4aXN0LCBzaW5jZSB0aGUgcmVnaXN0cnkgZ2F0ZXMgc3VzcGVuc2lvbiB2aWEgaXNEZWxpdmVyeUlkbGVcbiAgLy8gYW5kIGEgZGVhZCBkaXNwZW5zZXIgd291bGQgd2VkZ2UgdGhlIHJ1bi5cbiAgY29uc3QgcmVhcm1BZnRlclJlamVjdGlvbiA9ICgpID0+IHtcbiAgICBzZXRUaW1lb3V0KGNoZWNrLCA1MCk7XG4gIH07XG4gIGNvbnN0IGNoZWNrID0gKCkgPT4ge1xuICAgIGlmIChiYXJyaWVycy5zaXplID09PSAwKSB7XG4gICAgICAvLyBEb3JtYW50LiBUaGUgbmV4dCByZWdpc3RlckRlbGl2ZXJ5QmFycmllciByZS1hcm1zLlxuICAgICAgYWN0aXZlQmFycmllclNhZmV0eU5ldHMuZGVsZXRlKGN0eCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICghY2FuUmV0aXJlQWJhbmRvbmVkQmFycmllcnMoY3R4KSkge1xuICAgICAgLy8gQSBkZWxpdmVyeSBpcyBoeWRyYXRpbmcgb3IgY29tbWl0dGVkLWJ1dC1wYXJrZWQgb24gaXRzIGRlZmVycmFsOyBsZXRcbiAgICAgIC8vIHRoZSBxdWV1ZSBkcmFpbiBhbmQgcmUtY2hlY2sgYSB0aWNrIGxhdGVyIChzYW1lIGNhZGVuY2UgYXNcbiAgICAgIC8vIHNjaGVkdWxlV2hlbklkbGUpLlxuICAgICAgY3R4LnByb21pc2VRdWV1ZS50aGVuKHJlYXJtLCByZWFybUFmdGVyUmVqZWN0aW9uKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gSWRsZSB3aXRoIGVudHJpZXMgbGVmdDogbm90aGluZyByZW1haW5pbmcgZGVsaXZlcnMgb24gaXRzIG93biwgc29cbiAgICAvLyByZWxlYXNlIHBhcmtlZCBjaGFpbnMgZnJvbSB0aGUgaGVhZDogbG93ZXN0IGluZGV4IGZpcnN0LCBvbmUgYXQgYVxuICAgIC8vIHRpbWUsIHJlLXJlYWRpbmcgaWRsZSBiZXR3ZWVuIHJldGlyZW1lbnRzLiBBIHJldGlyZW1lbnQgdGhhdCB3YWtlcyBhXG4gICAgLy8gY2hhaW4gZmxpcHMge0BsaW5rIGhhc1BhcmtlZENvbW1pdHRlZERlbGl2ZXJ5fSBzeW5jaHJvbm91c2x5IChpdCBpc1xuICAgIC8vIGNvbXB1dGVkIGZyb20gdGhlIHJlZ2lzdHJ5IHRoaXMgbG9vcCBqdXN0IG11dGF0ZWQpLCB3aGljaCBzdG9wcyB0aGVcbiAgICAvLyBzd2VlcCBzbyB0aGUgY2hhaW4gZGVsaXZlcnMgYmVmb3JlIGFueXRoaW5nIGFib3ZlIGl0IGlzIHJlbGVhc2VkLiBBXG4gICAgLy8gcmV0aXJlbWVudCB0aGF0IHdha2VzIG5vdGhpbmcgKGEgc3RhbGUgcGF5bG9hZCBubyBkZWxpdmVyeSBnYXRlcyBvbilcbiAgICAvLyBrZWVwcyB0aGUgc3dlZXAgZ29pbmcsIHNvIGEgYmFja2xvZyBvZiB0aG9zZSBkcmFpbnMgaW4gT05FIGlkbGVcbiAgICAvLyBvYnNlcnZhdGlvbiwgc2luY2UgcGFjaW5nIHRoZW0gb25lIHBlciB0aW1lciB0aWNrIHdvdWxkIGhvbGRcbiAgICAvLyBjb25zdW1lZC1idXQtdW5kZWxpdmVyZWQgZXZlbnRzIGhvc3RhZ2UgbG9uZyBlbm91Z2ggdG8gdHJpcCB0aGUgZXZlbnRzXG4gICAgLy8gY29uc3VtZXIncyB1bmNvbnN1bWVkLWV2ZW50IGRlYWRsaW5lIGFuZCBmYWlsIGhlYWx0aHkgcmVwbGF5cy5cbiAgICB3aGlsZSAoYmFycmllcnMuc2l6ZSA+IDAgJiYgY2FuUmV0aXJlQWJhbmRvbmVkQmFycmllcnMoY3R4KSkge1xuICAgICAgbGV0IGxvd2VzdEluZGV4OiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gICAgICBsZXQgbG93ZXN0RW50cnk6IERlbGl2ZXJ5QmFycmllckVudHJ5IHwgdW5kZWZpbmVkO1xuICAgICAgZm9yIChjb25zdCBbaW5kZXgsIGVudHJ5XSBvZiBiYXJyaWVycykge1xuICAgICAgICBpZiAobG93ZXN0SW5kZXggPT09IHVuZGVmaW5lZCB8fCBpbmRleCA8IGxvd2VzdEluZGV4KSB7XG4gICAgICAgICAgbG93ZXN0SW5kZXggPSBpbmRleDtcbiAgICAgICAgICBsb3dlc3RFbnRyeSA9IGVudHJ5O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBsb3dlc3RFbnRyeT8ucmV0aXJlKCk7XG4gICAgfVxuICAgIHNldFRpbWVvdXQoY2hlY2ssIDApO1xuICB9O1xuICBzZXRUaW1lb3V0KGNoZWNrLCAwKTtcbn1cblxuLyoqXG4gKiBXaGV0aGVyIHRoZSBzYWZldHktbmV0IGRpc3BlbnNlciBtYXkgcmV0aXJlIGFiYW5kb25lZCBiYXJyaWVycyByaWdodCBub3c6XG4gKiBubyBoeWRyYXRpb24gaW4gZmxpZ2h0IGFuZCBubyBjb21taXR0ZWQgZGVsaXZlcnkgc3RpbGwgd29ya2luZyB0aHJvdWdoIGl0c1xuICogZGV0YWNoZWQgZGVmZXJyYWwuIFRoaXMgaXMgZGVsaWJlcmF0ZWx5IFdFQUtFUiB0aGFuIHtAbGluayBpc0RlbGl2ZXJ5SWRsZX06XG4gKiB0aGUgZGlzcGVuc2VyIGlzIHdoYXQgZW1wdGllcyB0aGUgcmVnaXN0cnksIHNvIGdhdGluZyBpdCBvbiByZWdpc3RyeVxuICogZW1wdGluZXNzIHdvdWxkIGdhdGUgaXRzIG93biB3b3JrLlxuICovXG5mdW5jdGlvbiBjYW5SZXRpcmVBYmFuZG9uZWRCYXJyaWVycyhjdHg6IFdvcmtmbG93T3JjaGVzdHJhdG9yQ29udGV4dCk6IGJvb2xlYW4ge1xuICByZXR1cm4gY3R4LnBlbmRpbmdEZWxpdmVyaWVzID09PSAwICYmICFoYXNQYXJrZWRDb21taXR0ZWREZWxpdmVyeShjdHgpO1xufVxuXG4vKipcbiAqIFdoZXRoZXIgc29tZSByZWdpc3RlcmVkIGJyYW5jaC1kZWNpZGluZyBkZWxpdmVyeSBpcyBnb2luZyB0byByZWFjaCB0aGVcbiAqIHdvcmtmbG93IHdpdGhvdXQgYW55IGZ1cnRoZXIgaGVscCAoaXQgaXMgYXJtZWQgYW5kIG5vdCB0cmFuc2l0aXZlbHkgcGFya2VkXG4gKiBiZWhpbmQgYW4gdW5jbGFpbWVkIGJ1ZmZlcmVkIHBheWxvYWQsIHNlZSB7QGxpbmsgcmVzb2x2ZXNPbkl0c093bn0pIGJ1dFxuICogaGFzIG5vdCBiZWVuIGhhbmRlZCBvdmVyIHlldC5cbiAqXG4gKiBUaGlzIGlzIHRoZSBkZWxpdmVyeSBzdGF0ZSBgcGVuZGluZ0RlbGl2ZXJpZXNgIGNhbm5vdCBzZWUuIFRoYXQgY291bnRlclxuICogY292ZXJzIHRoZSBoeWRyYXRpb24gd2luZG93IGluc2lkZSBhIHNlcmlhbCBgcHJvbWlzZVF1ZXVlYCBzbG90IGFuZCBpc1xuICogcmVsZWFzZWQgdGhlcmUsIHdoaWxlIHRoZSBkZWxpdmVyeSdzIGByZXNvbHZlKClgIHJ1bnMgbGF0ZXIsIGZyb20gYVxuICogZGV0YWNoZWQgY29udGludWF0aW9uIGJlaGluZCB7QGxpbmsgYXdhaXRFYXJsaWVyRGVsaXZlcmllc30sIGluY2x1ZGluZyBpdHNcbiAqIG1hY3JvdGFzayB5aWVsZCB3aGVuZXZlciB0aGUgZGVsaXZlcnkgaGFkIHRvIGRlZmVyLiBSZXBsYXlpbmcgYSBiYXRjaCBvZiBOXG4gKiBwYXJhbGxlbCBzdGVwIHJlc3VsdHMgY29uc3VtZWQgaW4gb25lIGRyYWluIHdpbmRvdyBsZWF2ZXMgTi0xIG9mIHRoZW1cbiAqIHBhcmtlZCBvbiB0aGF0IHlpZWxkIHdpdGggYHBlbmRpbmdEZWxpdmVyaWVzYCBhbHJlYWR5IGF0IDAuIEFuIGlkbGUgY2hlY2tcbiAqIGFybWVkIGR1cmluZyB0aGUgc2FtZSB3aW5kb3cgKGEgcGVuZGluZyBgc2xlZXAoKWAgYXJtcyBvbmUgb24gZXZlcnkgcmVwbGF5KVxuICogY291bGQgdGhlbiBvYnNlcnZlIFwiaWRsZVwiIG1pZC1kZWZlcnJhbCBhbmQgcmFpc2UgYSBgV29ya2Zsb3dTdXNwZW5zaW9uYFxuICogQkVGT1JFIHRoZSB3b3JrZmxvdydzIG93biBjb250aW51YXRpb25zIHJhbjogYSBzdXNwZW5zaW9uIGNhcnJ5aW5nIG5vbmUgb2ZcbiAqIHRoZSBmb2xsb3ctdXAgd29yayB0aGUgYmF0Y2ggd2FzIGFib3V0IHRvIGNyZWF0ZSwgd2hpY2ggdGhlIHJ1bnRpbWVcbiAqIGR1dGlmdWxseSBzY2hlZHVsZXMgYXMgbm90aGluZywgbGVhdmluZyB0aGUgcnVuIGRvcm1hbnQgdW50aWwgYW4gdW5yZWxhdGVkXG4gKiB0aW1lciBmaXJlcyAodmVyY2VsL3dvcmtmbG93IzMxODMpLlxuICpcbiAqIERlbGl2ZXJpZXMgdGhhdCBkbyBOT1QgcmVzb2x2ZSBvbiB0aGVpciBvd24gbXVzdCBiZSBleGNsdWRlZCwgbm90IGZvclxuICogYWNjdXJhY3kgYnV0IGZvciB0ZXJtaW5hdGlvbjogYW4gdW5jbGFpbWVkIGJ1ZmZlcmVkIGhvb2sgcGF5bG9hZCBpcyByZXRpcmVkXG4gKiBCWSB0aGUgaWRsZSBzYWZldHkgbmV0IGluIHtAbGluayByZWdpc3RlckRlbGl2ZXJ5QmFycmllcn0sIHNvIGNvdW50aW5nIGl0XG4gKiBoZXJlIHdvdWxkIGdhdGUgaXRzIG93biByZXRpcmVtZW50LiBUaGF0IHJlYXNvbmluZyBleHRlbmRzIHRvIHdoYXRldmVyIGlzXG4gKiBwYXJrZWQgYmVoaW5kIHN1Y2ggYSBwYXlsb2FkIChhIHdhaXQsIGFuZCBhIHN0ZXAgZ2F0aW5nIG9uIHRoYXQgd2FpdCkgZm9yXG4gKiB0aGUgc2FtZSByZWFzb246IHRoZSB3aG9sZSBjaGFpbiBtb3ZlcyBvbmx5IG9uY2UgdGhlIG5ldCBmaXJlcywgYW5kIGl0XG4gKiBjYW5ub3QgZmlyZSB3aGlsZSB0aGUgY2hhaW4gaXMgY291bnRlZC4gU2VsZi1yZXNvbHZpbmcgZGVsaXZlcmllcyBhbHdheXNcbiAqIGRlbGl2ZXIgZnJvbSB0aGVpciBvd24gY2hhaW5zIChzZWUgdGhlIElOVkFSSUFOVCBvblxuICoge0BsaW5rIHJlZ2lzdGVyRGVsaXZlcnlCYXJyaWVyfSkgYW5kIG5ldmVyIG5lZWQgdGhhdCBuZXQsIHNvIHdhaXRpbmcgb25cbiAqIHRoZW0gaXMgZGVhZGxvY2stZnJlZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhhc1BhcmtlZENvbW1pdHRlZERlbGl2ZXJ5KFxuICBjdHg6IFdvcmtmbG93T3JjaGVzdHJhdG9yQ29udGV4dFxuKTogYm9vbGVhbiB7XG4gIGNvbnN0IGJhcnJpZXJzID0gY3R4LnBlbmRpbmdEZWxpdmVyeUJhcnJpZXJzO1xuICBpZiAoIWJhcnJpZXJzIHx8IGJhcnJpZXJzLnNpemUgPT09IDApIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgLy8gU2hhcmVkIGFjcm9zcyB0aGlzIGNhbGwgb25seS4gU2VlIGByZXNvbHZlc09uSXRzT3duYC5cbiAgY29uc3Qgc2VsZlJlc29sdmluZyA9IG5ldyBNYXA8bnVtYmVyLCBib29sZWFuPigpO1xuICBmb3IgKGNvbnN0IFtpbmRleCwgZW50cnldIG9mIGJhcnJpZXJzKSB7XG4gICAgaWYgKHJlc29sdmVzT25JdHNPd24oYmFycmllcnMsIGluZGV4LCBlbnRyeSwgc2VsZlJlc29sdmluZykpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG5cbi8qKlxuICogV2hldGhlciBubyBkYXRhIGRlbGl2ZXJ5IChzdGVwIHJlc3VsdCwgaG9vayBwYXlsb2FkKSBpcyBpbiBmbGlnaHQgcmlnaHQgbm93LlxuICpcbiAqIFwiSW4gZmxpZ2h0XCIgaXMgdHdvIGRpc3RpbmN0IHdpbmRvd3MsIGVhY2ggd2l0aCBpdHMgb3duIGd1YXJkOlxuICogYHBlbmRpbmdEZWxpdmVyaWVzID4gMGAgY292ZXJzIGh5ZHJhdGlvbiBpbnNpZGUgdGhlIHNlcmlhbCBxdWV1ZSBzbG90cywgYW5kXG4gKiB7QGxpbmsgaGFzUGFya2VkQ29tbWl0dGVkRGVsaXZlcnl9IGNvdmVycyB0aGUgZGV0YWNoZWQgZ2FwIGJldHdlZW4gYSBzbG90XG4gKiByZWxlYXNpbmcgdGhhdCBjb3VudGVyIGFuZCB0aGUgZGVsaXZlcnkncyBgcmVzb2x2ZSgpYCBhY3R1YWxseSBydW5uaW5nLFxuICogZGVsaWJlcmF0ZWx5IG91dHNpZGUgYHBlbmRpbmdEZWxpdmVyaWVzYCAoc2VlIHN0ZXAudHMpLCBhbmQgaW52aXNpYmxlIHRvIGl0LlxuICpcbiAqIEFueXRoaW5nIHRoYXQgZGVjaWRlcyBhIHJlcGxheSBpcyBvdmVyLCBvciB0aGF0IGEgcmVwbGF5IHdlbnQgd3JvbmcsIGhhcyB0b1xuICogY29uc3VsdCB0aGlzIGZpcnN0OiB3aGlsZSBpdCBpcyBmYWxzZSB0aGUgd29ya2Zsb3cgVk0gaXMgbWlkLXJlYWN0aW9uLCBzb1xuICogd2hhdCBpdCBoYXMgYW5kIGhhcyBub3QgZG9uZSB5ZXQgc2F5cyBub3RoaW5nIGFib3V0IHRoZSBydW4uIFR3byBjYWxsZXJzXG4gKiByZWFkIGl0LCBmb3IgdGhlIHR3byBzdWNoIGRlY2lzaW9uczoge0BsaW5rIHNjaGVkdWxlV2hlbklkbGV9IGZvciB0aGVcbiAqIHN1c3BlbnNpb24sIGFuZCB0aGUgZXZlbnRzIGNvbnN1bWVyJ3MgdW5jb25zdW1lZC1ldmVudCBjaGVjayBmb3IgZGl2ZXJnZW5jZS5cbiAqXG4gKiBBIG5vbi1lbXB0eSBiYXJyaWVyIHJlZ2lzdHJ5IGNvdW50cyBhcyBpbiBmbGlnaHQsIGV2ZW4gd2hlbiBldmVyeSByZW1haW5pbmdcbiAqIGVudHJ5IGlzIHBhcmtlZCBiZWhpbmQgYW4gdW5jbGFpbWVkIGJ1ZmZlcmVkIHBheWxvYWQuIFRob3NlIGVudHJpZXMgb25seVxuICogbW92ZSB3aGVuIHRoZSBzYWZldHktbmV0IGRpc3BlbnNlciByZXRpcmVzIHRoZW0gKGxvd2VzdC1maXJzdCwgc2VlXG4gKiB7QGxpbmsgZW5zdXJlQmFycmllclNhZmV0eU5ldH0pLCBhbmQgdGhlIGRlbGl2ZXJpZXMgdGhleSByZWxlYXNlIGFyZSByZWFsXG4gKiB3b3JrZmxvdyByZWFjdGlvbnM6IGEgc3VzcGVuc2lvbiByYWlzZWQgYmVmb3JlIHRoZXkgcnVuIHdvdWxkIGJlIGNvbXB1dGVkXG4gKiBmcm9tIGEgVk0gdGhhdCBoYXMgbm90IHNlZW4gdGhlbSwgc2NoZWR1bGluZyBub25lIG9mIHRoZWlyIGZvbGxvdy11cCB3b3JrXG4gKiBhbmQgbGVhdmluZyB0aGUgcnVuIGRvcm1hbnQgKHRoZSB2ZXJjZWwvd29ya2Zsb3cjMzE4MyBzaGFwZSkuIFRoZSBkaXNwZW5zZXJcbiAqIGl0c2VsZiBpcyBnYXRlZCBvbiB7QGxpbmsgY2FuUmV0aXJlQWJhbmRvbmVkQmFycmllcnN9LCB0aGUgd2Vha2VyIHByZWRpY2F0ZVxuICogd2l0aG91dCB0aGUgcmVnaXN0cnkgdGVybSwgcHJlY2lzZWx5IHNvIGl0IGNhbiBkbyB0aGUgZHJhaW5pbmcgdGhhdCB0aGlzXG4gKiBwcmVkaWNhdGUgd2FpdHMgZm9yOyByZWdpc3RyeSBzaXplIHN0cmljdGx5IGRlY3JlYXNlcyBhdCBlYWNoIHJldGlyZW1lbnQsXG4gKiBzbyBpZGxlIGlzIGFsd2F5cyByZWFjaGVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNEZWxpdmVyeUlkbGUoY3R4OiBXb3JrZmxvd09yY2hlc3RyYXRvckNvbnRleHQpOiBib29sZWFuIHtcbiAgcmV0dXJuIChcbiAgICBjdHgucGVuZGluZ0RlbGl2ZXJpZXMgPT09IDAgJiZcbiAgICAoIWN0eC5wZW5kaW5nRGVsaXZlcnlCYXJyaWVycyB8fCBjdHgucGVuZGluZ0RlbGl2ZXJ5QmFycmllcnMuc2l6ZSA9PT0gMClcbiAgKTtcbn1cblxuLyoqXG4gKiBTY2hlZHVsZSBhIGNhbGxiYWNrIHRvIGZpcmUgb25seSBhZnRlciBhbGwgcGVuZGluZyBkYXRhIGRlbGl2ZXJpZXNcbiAqIChzdGVwIHJlc3VsdHMsIGhvb2sgcGF5bG9hZHMpIGFuZCBhc3luYyBkZXNlcmlhbGl6YXRpb24gaGF2ZSBjb21wbGV0ZWQuXG4gKiBVc2VzIGEgcG9sbGluZyBsb29wOiBzZXRUaW1lb3V0KDApIOKGkiBjaGVjayBwZW5kaW5nRGVsaXZlcmllcyBhbmQgdGhlXG4gKiBiYXJyaWVyIHJlZ2lzdHJ5IOKGkiBpZiBhbnl0aGluZyBpcyBzdGlsbCBpbiBmbGlnaHQsIHdhaXQgZm9yIHByb21pc2VRdWV1ZSDihpJcbiAqIHJlcGVhdC4gVGhpcyBoYW5kbGVzIHRoZSBtdWx0aS1yb3VuZCBkZWxpdmVyeSBwYXR0ZXJuIHdoZXJlIGVhY2ggaG9va1xuICogcGF5bG9hZCBkZWxpdmVyeSBjeWNsZSBhcHBlbmRzIG5ldyBhc3luYyB3b3JrIHRvIHRoZSBwcm9taXNlUXVldWUuIFdoYXRcbiAqIGNvdW50cyBhcyBpbiBmbGlnaHQgaXMge0BsaW5rIGlzRGVsaXZlcnlJZGxlfS5cbiAqXG4gKiBUaGUgaW5pdGlhbCBgc2V0VGltZW91dCgwKWAgbWFjcm90YXNrIGlzIGxvYWQtYmVhcmluZyBhbmQgbXVzdCBOT1QgYmVcbiAqIGRvd25ncmFkZWQgdG8gYSBtaWNyb3Rhc2sgKGBxdWV1ZU1pY3JvdGFza2AvYFByb21pc2UucmVzb2x2ZSgpLnRoZW5gKS5cbiAqIGBwZW5kaW5nRGVsaXZlcmllc2Agb25seSBndWFyZHMgdGhlIGhvc3Qtc2lkZSBoeWRyYXRpb24gd2luZG93OyBiZXR3ZWVuIGFcbiAqIGRlbGl2ZXJ5J3MgYHJlc29sdmUoKWAgYW5kIHRoZSB3b3JrZmxvdyBWTSBib2R5IHJ1bm5pbmcgaXRzIGNvbnRpbnVhdGlvbiB0b1xuICogcmVnaXN0ZXIgdGhlIG5leHQgc3Vic2NyaWJlciwgYHBlbmRpbmdEZWxpdmVyaWVzYCBpcyBhbHJlYWR5IDAgZXZlbiB0aG91Z2hcbiAqIHRoZSBWTSBpcyBtaWQtcmVhY3Rpb24uIE5vZGUgZG9lcyBub3QgZ3VhcmFudGVlIGEgbWljcm90YXNrIHNjaGVkdWxlZCBpblxuICogdGhlIGhvc3QgY29udGV4dCBzZXR0bGVzIGFmdGVyIHRoZSBjcm9zcy1WTSBwcm9taXNlIGNoYWluIChyZXNvbHZlIGluIGhvc3RcbiAqIOKGkiB3b3JrZmxvdyBjb2RlIGluIFZNIOKGkiBzdWJzY3JpYmUgYmFjayBpbiBob3N0KTsgdGhlIG1hY3JvdGFzayBib3VuZGFyeVxuICogZ2l2ZXMgdGhhdCBjaGFpbiB0aW1lIHRvIHJ1biwgc28gdGhlIHN1c3BlbnNpb24gZG9lcyBub3QgcHJlZW1wdCBhIHNpYmxpbmdcbiAqIGRlbGl2ZXJ5IHN0aWxsIGluIGZsaWdodC4gRW1waXJpY2FsbHksIHJlcGxhY2luZyBpdCB3aXRoIGBxdWV1ZU1pY3JvdGFza2BcbiAqIGJyZWFrcyBob29rL3NsZWVwIGBQcm9taXNlLnJhY2VgIG9yZGVyaW5nIChDb3JydXB0ZWRFdmVudExvZ0Vycm9yKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNjaGVkdWxlV2hlbklkbGUoXG4gIGN0eDogV29ya2Zsb3dPcmNoZXN0cmF0b3JDb250ZXh0LFxuICBmbjogKCkgPT4gdm9pZFxuKTogdm9pZCB7XG4gIGNvbnN0IGNoZWNrID0gKCkgPT4ge1xuICAgIGlmICghaXNEZWxpdmVyeUlkbGUoY3R4KSkge1xuICAgICAgLy8gQSBkZWxpdmVyeSBpcyBzdGlsbCBoeWRyYXRpbmcsIG9yIGlzIGNvbW1pdHRlZCBidXQgcGFya2VkIGJlaGluZCBpdHNcbiAgICAgIC8vIGRlZmVycmFsICh3aG9zZSByZXNvbHZlIHJ1bnMgb24gYSBkZXRhY2hlZCB0aW1lciwgbm90IHRoaXMgcXVldWUpLlxuICAgICAgLy8gRWl0aGVyIHdheTogbGV0IHRoZSBxdWV1ZSBkcmFpbiwgdGhlbiByZS1jaGVjayBhIHRpbWVyIHRpY2sgbGF0ZXIuXG4gICAgICBjdHgucHJvbWlzZVF1ZXVlLnRoZW4oKCkgPT4ge1xuICAgICAgICBzZXRUaW1lb3V0KGNoZWNrLCAwKTtcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBmbigpO1xuICAgIH1cbiAgfTtcbiAgc2V0VGltZW91dChjaGVjaywgMCk7XG59XG5cbi8qKiBTY2hlZHVsZSBhIGdlbmVyYXRpb24tZ3VhcmRlZCBzdXNwZW5zaW9uIGFmdGVyIGRlbGl2ZXJpZXMgc2V0dGxlLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNjaGVkdWxlV29ya2Zsb3dTdXNwZW5zaW9uKFxuICBjdHg6IFdvcmtmbG93T3JjaGVzdHJhdG9yQ29udGV4dFxuKTogdm9pZCB7XG4gIGNvbnN0IGdlbmVyYXRpb24gPSBjdHguc3VzcGVuc2lvbkdlbmVyYXRpb247XG4gIHNjaGVkdWxlV2hlbklkbGUoY3R4LCAoKSA9PiB7XG4gICAgaWYgKGdlbmVyYXRpb24gIT09IGN0eC5zdXNwZW5zaW9uR2VuZXJhdGlvbikgcmV0dXJuO1xuICAgIGN0eC5vbldvcmtmbG93RXJyb3IoXG4gICAgICBuZXcgV29ya2Zsb3dTdXNwZW5zaW9uKGN0eC5pbnZvY2F0aW9uc1F1ZXVlLCBjdHguZ2xvYmFsVGhpcylcbiAgICApO1xuICB9KTtcbn1cbiJdfQ==