@workflow/core 5.0.0-beta.42 → 5.0.0-beta.44

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