@workflow/core 5.0.0-beta.43 → 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.
- package/dist/capabilities.d.ts +4 -4
- package/dist/capabilities.js +5 -5
- package/dist/capture-stack.d.ts +1 -1
- package/dist/capture-stack.js +2 -2
- package/dist/class-serialization.d.ts +8 -8
- package/dist/class-serialization.js +9 -9
- package/dist/classify-error.js +5 -5
- package/dist/context-violation-error.d.ts +5 -5
- package/dist/context-violation-error.d.ts.map +1 -1
- package/dist/context-violation-error.js +5 -5
- package/dist/create-hook.d.ts +2 -2
- package/dist/create-hook.js +1 -1
- package/dist/define-hook.js +2 -2
- package/dist/describe-error.d.ts +7 -7
- package/dist/describe-error.js +8 -8
- package/dist/encryption.d.ts +5 -5
- package/dist/encryption.js +7 -7
- package/dist/events-consumer.d.ts +19 -7
- package/dist/events-consumer.d.ts.map +1 -1
- package/dist/events-consumer.js +33 -12
- package/dist/flushable-stream.d.ts +4 -4
- package/dist/flushable-stream.js +12 -12
- package/dist/global.d.ts +1 -1
- package/dist/global.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/log-format.d.ts +2 -2
- package/dist/log-format.js +5 -5
- package/dist/logger.js +4 -4
- package/dist/private.d.ts +21 -65
- package/dist/private.d.ts.map +1 -1
- package/dist/private.js +160 -38
- package/dist/replay-payload-cache.d.ts +1 -1
- package/dist/replay-payload-cache.js +4 -4
- package/dist/runtime/compute-instance.d.ts +4 -3
- package/dist/runtime/compute-instance.d.ts.map +1 -1
- package/dist/runtime/compute-instance.js +5 -4
- package/dist/runtime/constants.d.ts +24 -24
- package/dist/runtime/constants.d.ts.map +1 -1
- package/dist/runtime/constants.js +49 -43
- package/dist/runtime/count-step-started-events.d.ts +7 -7
- package/dist/runtime/count-step-started-events.js +4 -4
- package/dist/runtime/deployment-guard.d.ts +7 -7
- package/dist/runtime/deployment-guard.js +8 -8
- package/dist/runtime/get-port-lazy.d.ts +2 -2
- package/dist/runtime/get-port-lazy.d.ts.map +1 -1
- package/dist/runtime/get-port-lazy.js +37 -30
- package/dist/runtime/get-world-lazy.d.ts +2 -2
- package/dist/runtime/get-world-lazy.js +3 -3
- package/dist/runtime/helpers.d.ts +18 -18
- package/dist/runtime/helpers.js +27 -27
- package/dist/runtime/quickjs-entrypoint.d.ts +21 -10
- package/dist/runtime/quickjs-entrypoint.d.ts.map +1 -1
- package/dist/runtime/quickjs-entrypoint.js +199 -81
- package/dist/runtime/quickjs-runtime.d.ts +31 -15
- package/dist/runtime/quickjs-runtime.d.ts.map +1 -1
- package/dist/runtime/quickjs-runtime.js +126 -77
- package/dist/runtime/quickjs-serde.d.ts +10 -10
- package/dist/runtime/quickjs-serde.js +20 -20
- package/dist/runtime/replay-budget.d.ts +4 -4
- package/dist/runtime/replay-budget.js +5 -5
- package/dist/runtime/replay-recovery-reporter.d.ts +1 -1
- package/dist/runtime/replay-recovery-reporter.js +2 -2
- package/dist/runtime/resume-hook.d.ts +2 -2
- package/dist/runtime/resume-hook.js +27 -27
- package/dist/runtime/resume-latency.d.ts +25 -25
- package/dist/runtime/resume-latency.d.ts.map +1 -1
- package/dist/runtime/resume-latency.js +4 -4
- package/dist/runtime/run-id-time.d.ts +2 -2
- package/dist/runtime/run-id-time.js +5 -5
- package/dist/runtime/run.d.ts +21 -4
- package/dist/runtime/run.d.ts.map +1 -1
- package/dist/runtime/run.js +104 -10
- package/dist/runtime/runs.d.ts +4 -4
- package/dist/runtime/runs.js +2 -2
- package/dist/runtime/start.d.ts +3 -3
- package/dist/runtime/start.d.ts.map +1 -1
- package/dist/runtime/start.js +27 -23
- package/dist/runtime/step-executor.d.ts +14 -14
- package/dist/runtime/step-executor.d.ts.map +1 -1
- package/dist/runtime/step-executor.js +54 -39
- package/dist/runtime/step-latency.d.ts +14 -14
- package/dist/runtime/step-latency.js +11 -11
- package/dist/runtime/step-ownership.d.ts +6 -6
- package/dist/runtime/step-ownership.js +8 -8
- package/dist/runtime/step-single-flight.d.ts +1 -1
- package/dist/runtime/step-single-flight.d.ts.map +1 -1
- package/dist/runtime/step-single-flight.js +17 -11
- package/dist/runtime/suspension-handler.d.ts +29 -17
- package/dist/runtime/suspension-handler.d.ts.map +1 -1
- package/dist/runtime/suspension-handler.js +206 -71
- package/dist/runtime/unserializable-step.d.ts +34 -0
- package/dist/runtime/unserializable-step.d.ts.map +1 -0
- package/dist/runtime/unserializable-step.js +52 -0
- package/dist/runtime/vm-mode.d.ts +1 -1
- package/dist/runtime/vm-mode.js +2 -2
- package/dist/runtime/wait-continuation.d.ts +31 -9
- package/dist/runtime/wait-continuation.d.ts.map +1 -1
- package/dist/runtime/wait-continuation.js +44 -13
- package/dist/runtime/wait-until.d.ts +1 -1
- package/dist/runtime/wait-until.js +2 -2
- package/dist/runtime/world-compatibility.d.ts +20 -9
- package/dist/runtime/world-compatibility.d.ts.map +1 -1
- package/dist/runtime/world-compatibility.js +24 -13
- package/dist/runtime/world-init.d.ts +5 -5
- package/dist/runtime/world-init.js +6 -6
- package/dist/runtime/world.d.ts.map +1 -1
- package/dist/runtime/world.js +13 -3
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +300 -206
- package/dist/sealed-box.d.ts +7 -7
- package/dist/sealed-box.js +15 -15
- package/dist/serialization/client.js +2 -2
- package/dist/serialization/codec-devalue-vm.d.ts +1 -1
- package/dist/serialization/codec-devalue-vm.js +4 -4
- package/dist/serialization/codec-devalue.d.ts +1 -1
- package/dist/serialization/codec-devalue.js +2 -2
- package/dist/serialization/codec.d.ts +4 -4
- package/dist/serialization/codec.js +2 -2
- package/dist/serialization/compression.d.ts +12 -11
- package/dist/serialization/compression.d.ts.map +1 -1
- package/dist/serialization/compression.js +16 -15
- package/dist/serialization/encryption.d.ts +7 -7
- package/dist/serialization/encryption.d.ts.map +1 -1
- package/dist/serialization/encryption.js +8 -8
- package/dist/serialization/errors.js +2 -2
- package/dist/serialization/format.d.ts +6 -6
- package/dist/serialization/format.js +7 -7
- package/dist/serialization/hardened.d.ts +18 -18
- package/dist/serialization/hardened.d.ts.map +1 -1
- package/dist/serialization/hardened.js +41 -32
- package/dist/serialization/index.d.ts +1 -1
- package/dist/serialization/index.js +2 -2
- package/dist/serialization/reducers/class-vm.d.ts +1 -1
- package/dist/serialization/reducers/class-vm.js +2 -2
- package/dist/serialization/reducers/class.js +2 -2
- package/dist/serialization/reducers/common-vm.js +12 -12
- package/dist/serialization/reducers/common.js +12 -12
- package/dist/serialization/reducers/step-function-vm.d.ts +1 -1
- package/dist/serialization/reducers/step-function-vm.js +2 -2
- package/dist/serialization/reducers/step-function.js +2 -2
- package/dist/serialization/step.js +2 -2
- package/dist/serialization/types.d.ts +5 -5
- package/dist/serialization/types.js +2 -2
- package/dist/serialization/workflow-vm.d.ts +1 -1
- package/dist/serialization/workflow-vm.d.ts.map +1 -1
- package/dist/serialization/workflow-vm.js +13 -10
- package/dist/serialization-format.d.ts +11 -11
- package/dist/serialization-format.d.ts.map +1 -1
- package/dist/serialization-format.js +29 -23
- package/dist/serialization.d.ts +10 -10
- package/dist/serialization.js +98 -98
- package/dist/set-attributes.js +2 -2
- package/dist/source-map.d.ts +1 -1
- package/dist/source-map.d.ts.map +1 -1
- package/dist/source-map.js +18 -12
- package/dist/step/context-storage.d.ts +5 -5
- package/dist/step/context-storage.js +1 -1
- package/dist/step/writable-stream.d.ts +3 -3
- package/dist/step/writable-stream.js +7 -7
- package/dist/step.js +12 -12
- package/dist/symbols.d.ts +2 -2
- package/dist/symbols.js +3 -3
- package/dist/telemetry/semantic-conventions.d.ts +21 -13
- package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
- package/dist/telemetry/semantic-conventions.js +21 -15
- package/dist/telemetry.d.ts +3 -3
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +19 -10
- package/dist/test-support/orchestrator-context.d.ts.map +1 -1
- package/dist/test-support/orchestrator-context.js +12 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +2 -2
- package/dist/vm/index.js +4 -4
- package/dist/vm/script-cache.d.ts.map +1 -1
- package/dist/vm/script-cache.js +23 -17
- package/dist/vm/uint8array-base64.js +1 -1
- package/dist/workflow/abort-controller.d.ts +1 -1
- package/dist/workflow/abort-controller.js +12 -12
- package/dist/workflow/create-hook.js +2 -2
- package/dist/workflow/get-workflow-metadata.js +2 -2
- package/dist/workflow/hook.js +16 -16
- package/dist/workflow/set-attributes.d.ts +1 -1
- package/dist/workflow/set-attributes.js +2 -2
- package/dist/workflow/sleep.js +2 -2
- package/dist/workflow/world-init-stub.d.ts +1 -1
- package/dist/workflow/world-init-stub.js +2 -2
- package/dist/workflow.d.ts +2 -2
- package/dist/workflow.js +21 -7
- package/docs/api-reference/create-hook.mdx +15 -15
- package/docs/api-reference/create-webhook.mdx +15 -15
- package/docs/api-reference/define-hook.mdx +10 -10
- package/docs/api-reference/fatal-error.mdx +2 -2
- package/docs/api-reference/fetch.mdx +7 -7
- package/docs/api-reference/get-step-metadata.mdx +2 -2
- package/docs/api-reference/get-workflow-metadata.mdx +3 -3
- package/docs/api-reference/get-writable.mdx +7 -7
- package/docs/api-reference/index.mdx +1 -1
- package/docs/api-reference/retryable-error.mdx +1 -1
- package/docs/api-reference/set-attributes.mdx +2 -2
- package/docs/api-reference/sleep.mdx +3 -3
- package/docs/foundations/cancellation.mdx +31 -31
- package/docs/foundations/errors-and-retries.mdx +42 -11
- package/docs/foundations/hooks.mdx +35 -35
- package/docs/foundations/idempotency.mdx +9 -9
- package/docs/foundations/serialization.mdx +21 -22
- package/docs/foundations/starting-workflows.mdx +36 -37
- package/docs/foundations/streaming.mdx +46 -41
- package/docs/foundations/versioning.mdx +3 -3
- package/docs/foundations/workflows-and-steps.mdx +9 -9
- package/docs/how-it-works/cancellation.mdx +62 -62
- package/docs/how-it-works/code-transform.mdx +66 -54
- package/docs/how-it-works/encryption.mdx +25 -21
- package/docs/how-it-works/event-sourcing.mdx +53 -35
- package/docs/how-it-works/framework-integrations.mdx +12 -12
- package/docs/how-it-works/understanding-directives.mdx +21 -21
- 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
|
|
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
|
|
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
|
|
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)
|
|
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
|
|
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
|
|
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`
|
|
207
|
-
* a concurrent branch
|
|
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
|
-
*
|
|
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
|
|
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,7 +236,7 @@ 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
|
|
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
|
|
@@ -242,19 +247,120 @@ function computeResolvesOnItsOwn(barriers, index, entry, memo) {
|
|
|
242
247
|
* structural: safety-net retirements go through one per-context dispenser that
|
|
243
248
|
* only ever retires the lowest-index entry at delivery idle, and every
|
|
244
249
|
* retirement that wakes a chain flips {@link hasParkedCommittedDelivery} back
|
|
245
|
-
* to true, re-blocking the dispenser until the chain has drained
|
|
250
|
+
* to true, re-blocking the dispenser until the chain has drained. See
|
|
246
251
|
* {@link ensureBarrierSafetyNet}. (This used to rest on the FIFO of one idle
|
|
247
252
|
* poll per barrier, which held for a single parked segment but decayed to
|
|
248
|
-
* timing noise with several
|
|
253
|
+
* timing noise with several: the release order, and therefore the ULIDs
|
|
249
254
|
* drawn by the woken branches, then depended on how much log the replay had
|
|
250
255
|
* loaded. storm-log-replay.test.ts replays a production log corrupted exactly
|
|
251
256
|
* that way.)
|
|
252
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.
|
|
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
|
|
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
|
|
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
|
|
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
|
*/
|
|
@@ -336,7 +455,7 @@ export function registerDeliveryBarrier(ctx, eventIndex, kind, options = {}) {
|
|
|
336
455
|
// it is retired at idle so a later delivery gated on it cannot deadlock and
|
|
337
456
|
// the registry cannot leak an entry per abandoned delivery. Retirement goes
|
|
338
457
|
// through the context's single ordered dispenser rather than a per-barrier
|
|
339
|
-
// idle poll
|
|
458
|
+
// idle poll. See {@link ensureBarrierSafetyNet} for why the ORDER of these
|
|
340
459
|
// retirements is load-bearing.
|
|
341
460
|
ensureBarrierSafetyNet(ctx);
|
|
342
461
|
return {
|
|
@@ -351,6 +470,9 @@ export function registerDeliveryBarrier(ctx, eventIndex, kind, options = {}) {
|
|
|
351
470
|
* so the context interface (constructed literally by many test harnesses)
|
|
352
471
|
* needs no new field; entries drop with the context.
|
|
353
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.
|
|
354
476
|
const activeBarrierSafetyNets = new WeakSet();
|
|
355
477
|
/**
|
|
356
478
|
* The barrier registry's safety net: ONE idle-gated dispenser per context that
|
|
@@ -360,13 +482,13 @@ const activeBarrierSafetyNets = new WeakSet();
|
|
|
360
482
|
*
|
|
361
483
|
* Why one ordered dispenser and not a poll per barrier (which is what this
|
|
362
484
|
* replaced): the order of safety-net retirements decides the delivery order of
|
|
363
|
-
* every chain parked behind an unclaimed buffered hook payload
|
|
485
|
+
* every chain parked behind an unclaimed buffered hook payload: a hook the
|
|
364
486
|
* workflow never reads (a fire-and-forget `createHook`) parks every later
|
|
365
487
|
* armed wait/hook behind a barrier that only this net can retire. Per-barrier
|
|
366
488
|
* polls fire in whatever order their re-arm cycles land, and each re-arm
|
|
367
489
|
* attaches to a `promiseQueue` that grows between checks, so with several
|
|
368
490
|
* parked segments the release order decays to timing noise. Draws (`useStep`
|
|
369
|
-
* correlation ids) then depend on which segment happened to release first
|
|
491
|
+
* correlation ids) then depend on which segment happened to release first:
|
|
370
492
|
* concretely, on how MUCH log the replay loaded, since that decides what is in
|
|
371
493
|
* the registry. That is the mechanism behind slot-mode CORRUPTED_EVENT_LOG on
|
|
372
494
|
* storm-shaped runs (see storm-log-replay.test.ts, built from a production
|
|
@@ -376,12 +498,12 @@ const activeBarrierSafetyNets = new WeakSet();
|
|
|
376
498
|
* Retiring lowest-first is not merely tidy, it is the only order that cannot
|
|
377
499
|
* invert the log: every gate points from a higher index to a strictly lower
|
|
378
500
|
* one, so at delivery idle the lowest undelivered entry gates on nothing
|
|
379
|
-
* still registered
|
|
501
|
+
* still registered: it is the head of every parked chain (in practice, the
|
|
380
502
|
* unclaimed payload itself). Releasing it lets the chain above deliver
|
|
381
503
|
* through the ordinary barrier order; anything the release wakes flips
|
|
382
504
|
* {@link hasParkedCommittedDelivery} back to true, which re-blocks this
|
|
383
505
|
* dispenser until the chain has fully drained. A higher entry must never be
|
|
384
|
-
* retired while a lower one is registered
|
|
506
|
+
* retired while a lower one is registered, which is exactly the inversion
|
|
385
507
|
* described on {@link awaitEarlierDeliveries}.
|
|
386
508
|
*
|
|
387
509
|
* The dispenser goes dormant when the registry empties and is re-armed by the
|
|
@@ -418,16 +540,16 @@ function ensureBarrierSafetyNet(ctx) {
|
|
|
418
540
|
return;
|
|
419
541
|
}
|
|
420
542
|
// Idle with entries left: nothing remaining delivers on its own, so
|
|
421
|
-
// release parked chains from the head
|
|
543
|
+
// release parked chains from the head: lowest index first, one at a
|
|
422
544
|
// time, re-reading idle between retirements. A retirement that wakes a
|
|
423
545
|
// chain flips {@link hasParkedCommittedDelivery} synchronously (it is
|
|
424
546
|
// computed from the registry this loop just mutated), which stops the
|
|
425
547
|
// sweep so the chain delivers before anything above it is released. A
|
|
426
548
|
// retirement that wakes nothing (a stale payload no delivery gates on)
|
|
427
549
|
// keeps the sweep going, so a backlog of those drains in ONE idle
|
|
428
|
-
// observation
|
|
429
|
-
// undelivered events hostage long enough to trip the events
|
|
430
|
-
// unconsumed-event deadline and fail healthy replays.
|
|
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.
|
|
431
553
|
while (barriers.size > 0 && canRetireAbandonedBarriers(ctx)) {
|
|
432
554
|
let lowestIndex;
|
|
433
555
|
let lowestEntry;
|
|
@@ -456,19 +578,19 @@ function canRetireAbandonedBarriers(ctx) {
|
|
|
456
578
|
/**
|
|
457
579
|
* Whether some registered branch-deciding delivery is going to reach the
|
|
458
580
|
* workflow without any further help (it is armed and not transitively parked
|
|
459
|
-
* behind an unclaimed buffered payload
|
|
581
|
+
* behind an unclaimed buffered payload, see {@link resolvesOnItsOwn}) but
|
|
460
582
|
* has not been handed over yet.
|
|
461
583
|
*
|
|
462
584
|
* This is the delivery state `pendingDeliveries` cannot see. That counter
|
|
463
585
|
* covers the hydration window inside a serial `promiseQueue` slot and is
|
|
464
586
|
* released there, while the delivery's `resolve()` runs later, from a
|
|
465
|
-
* detached continuation behind {@link awaitEarlierDeliveries}
|
|
587
|
+
* detached continuation behind {@link awaitEarlierDeliveries}, including its
|
|
466
588
|
* macrotask yield whenever the delivery had to defer. Replaying a batch of N
|
|
467
589
|
* parallel step results consumed in one drain window leaves N-1 of them
|
|
468
590
|
* parked on that yield with `pendingDeliveries` already at 0. An idle check
|
|
469
591
|
* armed during the same window (a pending `sleep()` arms one on every replay)
|
|
470
592
|
* could then observe "idle" mid-deferral and raise a `WorkflowSuspension`
|
|
471
|
-
* BEFORE the workflow's own continuations ran
|
|
593
|
+
* BEFORE the workflow's own continuations ran: a suspension carrying none of
|
|
472
594
|
* the follow-up work the batch was about to create, which the runtime
|
|
473
595
|
* dutifully schedules as nothing, leaving the run dormant until an unrelated
|
|
474
596
|
* timer fires (vercel/workflow#3183).
|
|
@@ -477,7 +599,7 @@ function canRetireAbandonedBarriers(ctx) {
|
|
|
477
599
|
* accuracy but for termination: an unclaimed buffered hook payload is retired
|
|
478
600
|
* BY the idle safety net in {@link registerDeliveryBarrier}, so counting it
|
|
479
601
|
* here would gate its own retirement. That reasoning extends to whatever is
|
|
480
|
-
* parked behind such a payload
|
|
602
|
+
* parked behind such a payload (a wait, and a step gating on that wait) for
|
|
481
603
|
* the same reason: the whole chain moves only once the net fires, and it
|
|
482
604
|
* cannot fire while the chain is counted. Self-resolving deliveries always
|
|
483
605
|
* deliver from their own chains (see the INVARIANT on
|
|
@@ -489,7 +611,7 @@ export function hasParkedCommittedDelivery(ctx) {
|
|
|
489
611
|
if (!barriers || barriers.size === 0) {
|
|
490
612
|
return false;
|
|
491
613
|
}
|
|
492
|
-
// Shared across this call only
|
|
614
|
+
// Shared across this call only. See `resolvesOnItsOwn`.
|
|
493
615
|
const selfResolving = new Map();
|
|
494
616
|
for (const [index, entry] of barriers) {
|
|
495
617
|
if (resolvesOnItsOwn(barriers, index, entry, selfResolving)) {
|
|
@@ -504,7 +626,7 @@ export function hasParkedCommittedDelivery(ctx) {
|
|
|
504
626
|
* "In flight" is two distinct windows, each with its own guard:
|
|
505
627
|
* `pendingDeliveries > 0` covers hydration inside the serial queue slots, and
|
|
506
628
|
* {@link hasParkedCommittedDelivery} covers the detached gap between a slot
|
|
507
|
-
* releasing that counter and the delivery's `resolve()` actually running
|
|
629
|
+
* releasing that counter and the delivery's `resolve()` actually running,
|
|
508
630
|
* deliberately outside `pendingDeliveries` (see step.ts), and invisible to it.
|
|
509
631
|
*
|
|
510
632
|
* Anything that decides a replay is over, or that a replay went wrong, has to
|
|
@@ -517,7 +639,7 @@ export function hasParkedCommittedDelivery(ctx) {
|
|
|
517
639
|
* entry is parked behind an unclaimed buffered payload. Those entries only
|
|
518
640
|
* move when the safety-net dispenser retires them (lowest-first, see
|
|
519
641
|
* {@link ensureBarrierSafetyNet}), and the deliveries they release are real
|
|
520
|
-
* workflow reactions
|
|
642
|
+
* workflow reactions: a suspension raised before they run would be computed
|
|
521
643
|
* from a VM that has not seen them, scheduling none of their follow-up work
|
|
522
644
|
* and leaving the run dormant (the vercel/workflow#3183 shape). The dispenser
|
|
523
645
|
* itself is gated on {@link canRetireAbandonedBarriers}, the weaker predicate
|
|
@@ -566,4 +688,4 @@ export function scheduleWhenIdle(ctx, fn) {
|
|
|
566
688
|
};
|
|
567
689
|
setTimeout(check, 0);
|
|
568
690
|
}
|
|
569
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJpdmF0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9wcml2YXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBRUgsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBZ0JoRCxNQUFNLGtCQUFrQixHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsaUNBQWlDLENBQUMsQ0FBQztBQUV6RSxNQUFNLGFBQWEsR0FFZixVQUFVLENBQUM7QUFFZix3REFBd0Q7QUFDeEQsTUFBTSxlQUFlLEdBQUcsQ0FBQyxhQUFhLENBQUMsa0JBQWtCLENBQUMsS0FBSyxJQUFJLEdBQUcsRUFHbkUsQ0FBQyxDQUFDO0FBRUwsTUFBTSwyQkFBMkIsR0FBRyxJQUFJLEdBQUcsQ0FBQztJQUMxQyxpQ0FBaUM7SUFDakMseUJBQXlCO0lBQ3pCLHlCQUF5QjtDQUMxQixDQUFDLENBQUM7QUFFSCxTQUFTLHdCQUF3QixDQUFDLE1BQWM7SUFDOUMsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNqQyxJQUFJLEtBQUssQ0FBQyxNQUFNLEtBQUssQ0FBQyxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxNQUFNLEVBQUUsQ0FBQztRQUM5QyxPQUFPLEVBQUUsQ0FBQztJQUNaLENBQUM7SUFFRCxNQUFNLFVBQVUsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDNUIsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hCLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztJQUU1QyxNQUFNLFFBQVEsR0FBRyxDQUFDLGVBQXVCLEVBQUUsRUFBRTtRQUMzQyxJQUFJLGVBQWUsS0FBSyxVQUFVLEVBQUUsQ0FBQztZQUNuQyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLENBQUM7UUFDekMsQ0FBQztJQUNILENB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RCxPQUFPLEtBQUssQ0FBQztBQUNmLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0EwQkc7QUFDSCxNQUFNLFVBQVUsY0FBYyxDQUFDLEdBQWdDO0lBQzdELE9BQU8sQ0FDTCxHQUFHLENBQUMsaUJBQWlCLEtBQUssQ0FBQztRQUMzQixDQUFDLENBQUMsR0FBRyxDQUFDLHVCQUF1QixJQUFJLEdBQUcsQ0FBQyx1QkFBdUIsQ0FBQyxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQ3pFLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBb0JHO0FBQ0gsTUFBTSxVQUFVLGdCQUFnQixDQUM5QixHQUFnQyxFQUNoQyxFQUFjO0lBRWQsTUFBTSxLQUFLLEdBQUcsR0FBRyxFQUFFO1FBQ2pCLElBQUksQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUN6Qix1RUFBdUU7WUFDdkUscUVBQXFFO1lBQ3JFLHFFQUFxRTtZQUNyRSxHQUFHLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUU7Z0JBQ3pCLFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDdkIsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDO2FBQU0sQ0FBQztZQUNOLEVBQUUsRUFBRSxDQUFDO1FBQ1AsQ0FBQztJQUNILENBQUMsQ0FBQztJQUNGLFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDdkIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVXRpbHMgdXNlZCBieSB0aGUgYnVuZGxlciB3aGVuIHRyYW5zZm9ybWluZyBjb2RlXG4gKi9cblxuaW1wb3J0IHsgd2l0aFJlc29sdmVycyB9IGZyb20gJ0B3b3JrZmxvdy91dGlscyc7XG5pbXBvcnQgdHlwZSB7IFdvcmxkQ2FwYWJpbGl0aWVzIH0gZnJvbSAnQHdvcmtmbG93L3dvcmxkJztcbmltcG9ydCB0eXBlIHsgRXZlbnRzQ29uc3VtZXIgfSBmcm9tICcuL2V2ZW50cy1jb25zdW1lci5qcyc7XG5pbXBvcnQgdHlwZSB7IFF1ZXVlSXRlbSB9IGZyb20gJy4vZ2xvYmFsLmpzJztcbmltcG9ydCB0eXBlIHsgUmVwbGF5UGF5bG9hZENhY2hlIH0gZnJvbSAnLi9yZXBsYXktcGF5bG9hZC1jYWNoZS5qcyc7XG5pbXBvcnQgdHlwZSB7IFNlcmlhbGl6YWJsZSB9IGZyb20gJy4vc2NoZW1hcy5qcyc7XG5pbXBvcnQgdHlwZSB7IFBheWxvYWRLZXkgfSBmcm9tICcuL3NlcmlhbGl6YXRpb24vZW5jcnlwdGlvbi5qcyc7XG5cbmV4cG9ydCB0eXBlIFN0ZXBGdW5jdGlvbjxcbiAgQXJncyBleHRlbmRzIFNlcmlhbGl6YWJsZVtdID0gYW55W10sXG4gIFJlc3VsdCBleHRlbmRzIFNlcmlhbGl6YWJsZSB8IHVua25vd24gPSB1bmtub3duLFxuPiA9ICgoLi4uYXJnczogQXJncykgPT4gUHJvbWlzZTxSZXN1bHQ+KSAmIHtcbiAgbWF4UmV0cmllcz86IG51bWJlcjtcbiAgc3RlcElkPzogc3RyaW5nO1xufTtcblxuY29uc3QgUmVnaXN0ZXJlZFN0ZXBzS2V5ID0gU3ltYm9sLmZvcignQHdvcmtmbG93L2NvcmUvL3JlZ2lzdGVyZWRTdGVwcycpO1xuXG5jb25zdCBnbG9iYWxTeW1ib2xzOiB0eXBlb2YgZ2xvYmFsVGhpcyAmIHtcbiAgW1JlZ2lzdGVyZWRTdGVwc0tleV0/OiBNYXA8c3RyaW5nLCBTdGVwRnVuY3Rpb24+O1xufSA9IGdsb2JhbFRoaXM7XG5cbi8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9Bc3NpZ25JbkV4cHJlc3Npb25zOiAvXG5jb25zdCByZWdpc3RlcmVkU3RlcHMgPSAoZ2xvYmFsU3ltYm9sc1tSZWdpc3RlcmVkU3RlcHNLZXldID8/PSBuZXcgTWFwPFxuICBzdHJpbmcsXG4gIFN0ZXBGdW5jdGlvblxuPigpKTtcblxuY29uc3QgQlVJTFRJTl9SRVNQT05TRV9TVEVQX05BTUVTID0gbmV3IFNldChbXG4gICdfX2J1aWx0aW5fcmVzcG9uc2VfYXJyYXlfYnVmZmVyJyxcbiAgJ19fYnVpbHRpbl9yZXNwb25zZV9qc29uJyxcbiAgJ19fYnVpbHRpbl9yZXNwb25zZV90ZXh0Jyxcbl0pO1xuXG5mdW5jdGlvbiBnZXRTdGVwSWRBbGlhc0NhbmRpZGF0ZXMoc3RlcElkOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gIGNvbnN0IHBhcnRzID0gc3RlcElkLnNwbGl0KCcvLycpO1xuICBpZiAocGFydHMubGVuZ3RoICE9PSAzIHx8IHBhcnRzWzBdICE9PSAnc3RlcCcpIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBjb25zdCBtb2R1bGVQYXRoID0gcGFydHNbMV07XG4gIGNvbnN0IGZuTmFtZSA9IHBhcnRzWzJdO1xuICBjb25zdCBtb2R1bGVQYXRoQWxpYXNlcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4gIGNvbnN0IGFkZEFsaWFzID0gKGFsaWFzTW9kdWxlUGF0aDogc3RyaW5nKSA9PiB7XG4gICAgaWYgKGFsaWFzTW9kdWxlUGF0aCAhPT0gbW9kdWxlUGF0aCkge1xuICAgICAgbW9kdWxlUGF0aEFsaWFzZXMuYWRkKGFsaWFzTW9kdWxlUGF0aCk7XG4gICAgfVxuICB9O1xuXG4gIGlmIChtb2R1bGVQYXRoLnN0YXJ0c1dpdGgoJy4vd29ya2Zsb3dzLycpKSB7XG4gICAgY29uc3Qgd29ya2Zsb3dSZWxhdGl2ZVBhdGggPSBtb2R1bGVQYXRoLnNsaWNlKCcuLycubGVuZ3RoKTtcbiAgICBhZGRBbGlhcyhgLi9leGFtcGxlLyR7d29ya2Zsb3dSZWxhdGl2ZVBhdGh9YCk7XG4gICAgYWRkQWxpYXMoYC4vc3JjLyR7d29ya2Zsb3dSZWxhdGl2ZVBhdGh9YCk7XG4gIH0gZWxzZSBpZiAobW9kdWxlUGF0aC5zdGFydHNXaXRoKCcuL2V4YW1wbGUvd29ya2Zsb3dzLycpKSB7XG4gICAgY29uc3Qgd29ya2Zsb3dSZWxhdGl2ZVBhdGggPSBtb2R1bGVQYXRoLnNsaWNlKCcuL2V4YW1wbGUvJy5sZW5ndGgpO1xuICAgIGFkZEFsaWFzKGAuLyR7d29ya2Zsb3dSZWxhdGl2ZVBhdGh9YCk7XG4gICAgYWRkQWxpYXMoYC4vc3JjLyR7d29ya2Zsb3dSZWxhdGl2ZVBhdGh9YCk7XG4gIH0gZWxzZSBpZiAobW9kdWxlUGF0aC5zdGFydHNXaXRoKCcuL3NyYy93b3JrZmxvd3MvJykpIHtcbiAgICBjb25zdCB3b3JrZmxvd1JlbGF0aXZlUGF0aCA9IG1vZHVsZVBhdGguc2xpY2UoJy4vc3JjLycubGVuZ3RoKTtcbiAgICBhZGRBbGlhcyhgLi8ke3dvcmtmbG93UmVsYXRpdmVQYXRofWApO1xuICAgIGFkZEFsaWFzKGAuL2V4YW1wbGUvJHt3b3JrZmxvd1JlbGF0aXZlUGF0aH1gKTtcbiAgfVxuXG4gIHJldHVybiBBcnJheS5mcm9tKFxuICAgIG1vZHVsZVBhdGhBbGlhc2VzLFxuICAgIChhbGlhc01vZHVsZVBhdGgpID0+IGBzdGVwLy8ke2FsaWFzTW9kdWxlUGF0aH0vLyR7Zm5OYW1lfWBcbiAgKTtcbn1cblxuZnVuY3Rpb24gZ2V0QnVpbHRpblJlc3BvbnNlU3RlcEFsaWFzKHN0ZXBJZDogc3RyaW5nKTogU3RlcEZ1bmN0aW9uIHwgdW5kZWZpbmVkIHtcbiAgaWYgKCFCVUlMVElOX1JFU1BPTlNFX1NURVBfTkFNRVMuaGFzKHN0ZXBJZCkpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgZm9yIChjb25zdCBbcmVnaXN0ZXJlZFN0ZXBJZCwgc3RlcEZuXSBvZiByZWdpc3RlcmVkU3RlcHMuZW50cmllcygpKSB7XG4gICAgaWYgKHJlZ2lzdGVyZWRTdGVwSWQuZW5kc1dpdGgoYC8vJHtzdGVwSWR9YCkpIHtcbiAgICAgIHJldHVybiBzdGVwRm47XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBSZWdpc3RlciBhIHN0ZXAgZnVuY3Rpb24gdG8gYmUgc2VydmVkIGluIHRoZSBzZXJ2ZXIgYnVuZGxlLlxuICogQWxzbyBzZXRzIHRoZSBzdGVwSWQgcHJvcGVydHkgb24gdGhlIGZ1bmN0aW9uIGZvciBzZXJpYWxpemF0aW9uIHN1cHBvcnQuXG4gKlxuICogTm90ZTogVGhlIFNXQyBjb21waWxlciBwbHVnaW4gbm8gbG9uZ2VyIGdlbmVyYXRlcyBjYWxscyB0byB0aGlzIGZ1bmN0aW9uLlxuICogU3RlcCByZWdpc3RyYXRpb24gaXMgbm93IGlubGluZWQgYXMgYSBzZWxmLWNvbnRhaW5lZCBJSUZFIHRoYXQgd3JpdGVzXG4gKiBkaXJlY3RseSB0byB0aGUgZ2xvYmFsIE1hcCBhdCBTeW1ib2wuZm9yKFwiQHdvcmtmbG93L2NvcmUvL3JlZ2lzdGVyZWRTdGVwc1wiKS5cbiAqIFRoaXMgZnVuY3Rpb24gaXMga2VwdCBmb3IgaW50ZXJuYWwvdGVzdCB1c2Ugb25seS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyU3RlcEZ1bmN0aW9uKHN0ZXBJZDogc3RyaW5nLCBzdGVwRm46IFN0ZXBGdW5jdGlvbikge1xuICByZWdpc3RlcmVkU3RlcHMuc2V0KHN0ZXBJZCwgc3RlcEZuKTtcbiAgc3RlcEZuLnN0ZXBJZCA9IHN0ZXBJZDtcbn1cblxuLyoqXG4gKiBGaW5kIGEgcmVnaXN0ZXJlZCBzdGVwIGZ1bmN0aW9uIGJ5IG5hbWVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFN0ZXBGdW5jdGlvbihzdGVwSWQ6IHN0cmluZyk6IFN0ZXBGdW5jdGlvbiB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IGRpcmVjdE1hdGNoID0gcmVnaXN0ZXJlZFN0ZXBzLmdldChzdGVwSWQpO1xuICBpZiAoZGlyZWN0TWF0Y2gpIHtcbiAgICByZXR1cm4gZGlyZWN0TWF0Y2g7XG4gIH1cblxuICAvLyBTdXBwb3J0IGVxdWl2YWxlbnQgd29ya2Zsb3cgcGF0aCBhbGlhc2VzIGluIG1peGVkIHN5bWxpbmsgZW52aXJvbm1lbnRzLlxuICBmb3IgKGNvbnN0IGFsaWFzU3RlcElkIG9mIGdldFN0ZXBJZEFsaWFzQ2FuZGlkYXRlcyhzdGVwSWQpKSB7XG4gICAgY29uc3QgYWxpYXNNYXRjaCA9IHJlZ2lzdGVyZWRTdGVwcy5nZXQoYWxpYXNTdGVwSWQpO1xuICAgIGlmIChhbGlhc01hdGNoKSB7XG4gICAgICByZXR1cm4gYWxpYXNNYXRjaDtcbiAgICB9XG4gIH1cblxuICBjb25zdCBidWlsdGluQWxpYXNNYXRjaCA9IGdldEJ1aWx0aW5SZXNwb25zZVN0ZXBBbGlhcyhzdGVwSWQpO1xuICBpZiAoYnVpbHRpbkFsaWFzTWF0Y2gpIHtcbiAgICByZXR1cm4gYnVpbHRpbkFsaWFzTWF0Y2g7XG4gIH1cblxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG4vLyBOb3RlOiBfX3ByaXZhdGVfZ2V0Q2xvc3VyZVZhcnMgaXMgbm8gbG9uZ2VyIHJlLWV4cG9ydGVkIGhlcmUuXG4vLyBUaGUgU1dDIGNvbXBpbGVyIHBsdWdpbiBub3cgaW5saW5lcyBjbG9zdXJlIHZhcmlhYmxlIGFjY2VzcyBhcyBhXG4vLyBzZWxmLWNvbnRhaW5lZCBJSUZFIHRoYXQgcmVhZHMgZGlyZWN0bHkgZnJvbSB0aGUgZ2xvYmFsIEFzeW5jTG9jYWxTdG9yYWdlXG4vLyBhdCBTeW1ib2wuZm9yKFwiV09SS0ZMT1dfU1RFUF9DT05URVhUX1NUT1JBR0VcIikuXG5cbmV4cG9ydCBpbnRlcmZhY2UgV29ya2Zsb3dPcmNoZXN0cmF0b3JDb250ZXh0IHtcbiAgcnVuSWQ6IHN0cmluZztcbiAgZW5jcnlwdGlvbktleTogUGF5bG9hZEtleSB8IHVuZGVmaW5lZDtcbiAgd29ybGRDYXBhYmlsaXRpZXM/OiBXb3JsZENhcGFiaWxpdGllcztcbiAgZ2xvYmFsVGhpczogdHlwZW9mIGdsb2JhbFRoaXM7XG4gIC8qKlxuICAgKiBJbmNyZW1lbnRzIHdoZW4gYSBzdXNwZW5zaW9uIGlzIGFjY2VwdGVkIGFuZCBvbiBldmVyeSByZXRhaW5lZC1zZXNzaW9uXG4gICAqIHJlc3VtZS4gU1RFUCBzdXNwZW5zaW9uIHNpZ25hbHMgY2FwdHVyZSBpdCB3aGVuIHNjaGVkdWxlZCBhbmQgbm8tb3AgaWZcbiAgICogaXQgbW92ZWQgKHNlZSBzdGVwLnRzKSDigJQgdGhpcyBkcm9wcyBzYW1lLWJvdW5kYXJ5IHNpYmxpbmcgc2lnbmFscyBhbmRcbiAgICogdGltZXJzIHF1ZXVlZCBhdCBib3VuZGFyeSBOIHRoYXQgd291bGQgZmlyZSBhZnRlciB0aGUgc2Vzc2lvbiByZXN1bWVkXG4gICAqIGludG8gYm91bmRhcnkgTisxLiBTbGVlcC9ob29rL2F0dHJpYnV0ZSBzaWduYWxzIGFyZSBpbnRlbnRpb25hbGx5XG4gICAqIHVuZ3VhcmRlZDogdGhlaXIgcHJlc2VuY2UgbWFrZXMgdGhlIGJvdW5kYXJ5IHVucmV0YWluYWJsZSwgc28gYSBsYXRlXG4gICAqIHNpZ25hbCBjb3JyZWN0bHkgZGVtb3RlcyB0aGUgc2Vzc2lvbiAod29ya2Zsb3cudHMgYG9uV29ya2Zsb3dFcnJvcmApLlxuICAgKi9cbiAgc3VzcGVuc2lvbkdlbmVyYXRpb246IG51bWJlcjtcbiAgZXZlbnRzQ29uc3VtZXI6IEV2ZW50c0NvbnN1bWVyO1xuICAvKipcbiAgICogTWFwIG9mIHBlbmRpbmcgaW52b2NhdGlvbnMga2V5ZWQgYnkgY29ycmVsYXRpb25JZC5cbiAgICogVXNpbmcgTWFwIGluc3RlYWQgb2YgQXJyYXkgZm9yIE8oMSkgbG9va3VwL2RlbGV0ZSBvcGVyYXRpb25zLlxuICAgKi9cbiAgaW52b2NhdGlvbnNRdWV1ZTogTWFwPHN0cmluZywgUXVldWVJdGVtPjtcbiAgb25Xb3JrZmxvd0Vycm9yOiAoZXJyb3I6IEVycm9yKSA9PiB2b2lkO1xuICAvKipcbiAgICogTWludHMgdGhlIFVMSUQgYm9keSBvZiBhIGNvcnJlbGF0aW9uIGlkLiBFdmVyeSBlbnRpdHkgYSByZXBsYXkgY3JlYXRlc1xuICAgKiBkcmF3cyBmcm9tIHRoaXMgb25lIG1vbm90b25pYyBzZXF1ZW5jZSwgc28gYW4gaWQgaXMgYW4gb3JkaW5hbCBvdmVyIHRoZVxuICAgKiB3aG9sZSBydW4gYW5kIGJvdGggcmVwbGF5cyBvZiBhIHJ1biBtdXN0IGRyYXcgaW4gdGhlIHNhbWUgb3JkZXIuXG4gICAqL1xuICBnZW5lcmF0ZVVsaWQ6ICgpID0+IHN0cmluZztcbiAgZ2VuZXJhdGVOYW5vaWQ6ICgpID0+IHN0cmluZztcbiAgLyoqXG4gICAqIFNlcXVlbnRpYWwgcHJvbWlzZSBxdWV1ZSB0aGF0IGVuc3VyZXMgYWxsIGV2ZW50LWRyaXZlbiBwcm9taXNlIHJlc29sdXRpb25zXG4gICAqIChzdGVwIHJlc3VsdHMsIGhvb2sgcGF5bG9hZHMsIGZhaWx1cmVzLCBzdXNwZW5zaW9ucykgaGFwcGVuIGluIGV2ZW50IGxvZ1xuICAgKiBvcmRlci4gRXZlcnkgcmVzb2x2ZSwgcmVqZWN0LCBvciB3b3JrZmxvdyBlcnJvciBpcyBjaGFpbmVkIHRocm91Z2ggdGhpc1xuICAgKiBxdWV1ZSBzbyB0aGF0IGV2ZW4gaWYgaW5kaXZpZHVhbCBvcGVyYXRpb25zIHRha2UgdmFyaWFibGUgdGltZSAoZS5nLixcbiAgICogYXN5bmMgZGVjcnlwdGlvbiksIHByb21pc2VzIHJlc29sdmUgZGV0ZXJtaW5pc3RpY2FsbHkuXG4gICAqL1xuICBwcm9taXNlUXVldWU6IFByb21pc2U8dm9pZD47XG4gIC8qKlxuICAgKiBDb3VudGVyIG9mIGluLWZsaWdodCBhc3luYyBkYXRhIGRlbGl2ZXJ5IG9wZXJhdGlvbnMgKHN0ZXAgcmVzdWx0XG4gICAqIGh5ZHJhdGlvbiwgaG9vayBwYXlsb2FkIGh5ZHJhdGlvbiwgYWJvcnQgc2lnbmFsIGh5ZHJhdGlvbikuIFN1c3BlbnNpb25zXG4gICAqIG11c3Qgd2FpdCBmb3IgdGhpcyB0byByZWFjaCAwIGJlZm9yZSBmaXJpbmcsIHRvIGF2b2lkIHByZWVtcHRpbmcgZGF0YVxuICAgKiBkZWxpdmVyeSDigJQgZS5nLiBkZWh5ZHJhdGluZyBhIHN0ZXAncyBhcmd1bWVudHMgd2hpbGUgYW4gYWJvcnQgdGhhdCBzaG91bGRcbiAgICogYmUgcmVmbGVjdGVkIGluIHRob3NlIGFyZ3VtZW50cyBpcyBzdGlsbCBoeWRyYXRpbmcgaXRzIHJlYXNvbi5cbiAgICovXG4gIHBlbmRpbmdEZWxpdmVyaWVzOiBudW1iZXI7XG4gIC8qKlxuICAgKiBPcmRlcmVkIHJlZ2lzdHJ5IG9mIGluLWZsaWdodCBcImJyYW5jaC1kZWNpZGluZ1wiIGRlbGl2ZXJpZXMg4oCUIHRoZVxuICAgKiByZXNvbHV0aW9ucyBhIHdvcmtmbG93IHR5cGljYWxseSBgUHJvbWlzZS5yYWNlYHMgb24sIG9yIGF3YWl0cyBmcm9tXG4gICAqIGluZGVwZW5kZW50IGNvbmN1cnJlbnQgYnJhbmNoZXM6IGhvb2sgcGF5bG9hZHMgKGBob29rX3JlY2VpdmVkYCksIHdhaXRcbiAgICogY29tcGxldGlvbnMgKGB3YWl0X2NvbXBsZXRlZGApLCBhbmQgc3RlcCByZXN1bHRzIChgc3RlcF9jb21wbGV0ZWRgIC9cbiAgICogYHN0ZXBfZmFpbGVkYCkuIEtleWVkIGJ5IHRoZSBkZWxpdmVyeSdzIHBvc2l0aW9uIChpbmRleCkgaW4gdGhlIGNvbnN1bWVkXG4gICAqIGV2ZW50IGxvZy5cbiAgICpcbiAgICogVGhlIHByb2JsZW06IGVhY2ggb2YgdGhlc2UgcmVzb2x1dGlvbnMgcmVhY2hlcyB3b3JrZmxvdyBjb2RlIGFmdGVyIGFcbiAgICogZGlmZmVyZW50LCB3b3JrbG9hZC1kZXBlbmRlbnQgbnVtYmVyIG9mIG1pY3JvdGFzayBob3BzLiBBIGJ1ZmZlcmVkIGhvb2tcbiAgICogcGF5bG9hZCBpcyBvYnNlcnZlZCB2aWEgdGhlIGFzeW5jIGhvb2sgaXRlcmF0b3IgKGB5aWVsZCBhd2FpdCB0aGlzYCksXG4gICAqIGNvc3RpbmcgZXh0cmEgaG9wczsgYSBgd2FpdF9jb21wbGV0ZWRgIHJlc29sdmVzIHdpdGggZmV3ZXIsIGFuZCBhIHJldXNlZFxuICAgKiBzbGVlcCBjYW4gcmVzb2x2ZSBpbiBhbiBlbnRpcmVseSBlYXJsaWVyIGxvb3AgaXRlcmF0aW9uOyBhIHN0ZXAgcmVzdWx0IGlzXG4gICAqIGdhdGVkIG9uIGh5ZHJhdGlvbiB3aG9zZSBjb3N0IHZhcmllcyBiZXR3ZWVuIHJlcGxheXMgb2YgdGhlIFNBTUVcbiAgICogaW52b2NhdGlvbiDigJQgdGhlIGZpcnN0IHJlcGxheSBwYXlzIHRoZSBmdWxsIGRlY3J5cHQvZGVjb21wcmVzcy9yZXZpdmUsXG4gICAqIHdoaWxlIGxhdGVyIHJlcGxheXMgc2hhcmluZyB0aGUgaW52b2NhdGlvbidzIGBSZXBsYXlQYXlsb2FkQ2FjaGVgXG4gICAqIG1lbW8taGl0IHNtYWxsIHByaW1pdGl2ZSByZXN1bHRzIGFuZCByZXNvbHZlIGluIG9uZSBvciB0d28gaG9wcy4gRWl0aGVyXG4gICAqIHdheSwgdGhlIHJlc29sdXRpb24gdGhhdCB0aGUgY29tbWl0dGVkIGV2ZW50IGxvZyBvcmRlcmVkIGZpcnN0IGNhbiBsb3NlIGFcbiAgICogYFByb21pc2UucmFjZWAgKG9yIGEgYHVzZVN0ZXBgIFVMSUQgYWxsb2NhdGlvbikgdG8gYSBmYXN0ZXItIG9yXG4gICAqIGFscmVhZHktcmVzb2x2ZWQgY29tcGV0aXRvciwgZGl2ZXJnaW5nIGZyb20gdGhlIGxvZyBhbmQgc3VyZmFjaW5nIGFzXG4gICAqIGBDb3JydXB0ZWRFdmVudExvZ0Vycm9yYC5cbiAgICpcbiAgICogVGhlIGZpeCBpcyBhIHN0cmljdCwgZGV0ZXJtaW5pc3RpYyBkZWxpdmVyeSBvcmRlciBhbmNob3JlZCBvblxuICAgKiBldmVudC1sb2cgcG9zaXRpb246IGEgZGVsaXZlcnkgZG9lcyBub3QgcmVzb2x2ZSB0byB0aGUgd29ya2Zsb3cgdW50aWxcbiAgICogZXZlcnkgcmVsZXZhbnQgZWFybGllci1pbi1sb2cgZGVsaXZlcnkgaGFzIGJlZW4gZGVsaXZlcmVkLiBCZWNhdXNlIHRoZVxuICAgKiBnYXRlIGlzIFwidGhlIGVhcmxpZXIgZGVsaXZlcnkgcmVzb2x2ZWRcIiwgbm90IFwid29uIGEgdGltaW5nIHJhY2VcIiwgdGhlXG4gICAqIG91dGNvbWUgaXMgaW5kZXBlbmRlbnQgb2YgbWljcm90YXNrIGhvcHMsIGh5ZHJhdGlvbi9kZWNyeXB0aW9uIHRpbWUsXG4gICAqIGFuZCBgUHJvbWlzZS5yYWNlYCBhcmd1bWVudCBvcmRlci4gV2hpY2ggZWFybGllciBraW5kcyBhIGRlbGl2ZXJ5IGRlZmVyc1xuICAgKiBiZWhpbmQgaXMgc3BlbGxlZCBvdXQgb24ge0BsaW5rIGF3YWl0RWFybGllckRlbGl2ZXJpZXN9LlxuICAgKlxuICAgKiBJbmRleCBpcyB1c2VkIHJhdGhlciB0aGFuIHRoZSBgZXZlbnRJZGAgc3RyaW5nIGJlY2F1c2UgYGV2ZW50SWRgIGlzIGFuXG4gICAqIG9wYXF1ZSwgd29ybGQtYXNzaWduZWQgdmFsdWUgbm90IGd1YXJhbnRlZWQgdG8gc29ydCBpbiBjcmVhdGlvbiBvcmRlclxuICAgKiAob25seSB0aGUgYnVuZGxlZCBVTElEIHdvcmxkcyBoYXBwZW4gdG8pLlxuICAgKlxuICAgKiBPcHRpb25hbCBzbyBvbGRlci9vdXQtb2YtdHJlZSBjb250ZXh0cyAoYW5kIGxpZ2h0d2VpZ2h0IHRlc3QgaGFybmVzc2VzKVxuICAgKiB0aGF0IGRvIG5vdCBpbml0aWFsaXplIGl0IGRlZ3JhZGUgZ3JhY2VmdWxseSB0byB0aGUgcHJldmlvdXMgYmVoYXZpb3IuXG4gICAqL1xuICBwZW5kaW5nRGVsaXZlcnlCYXJyaWVycz86IE1hcDxudW1iZXIsIERlbGl2ZXJ5QmFycmllckVudHJ5PjtcbiAgLyoqXG4gICAqIEludm9jYXRpb24tc2NvcGVkIGNhY2hlIG9mIHByZXBhcmVkIHNlcmlhbGl6ZWQgcGF5bG9hZHMgYW5kIGltbXV0YWJsZSBmaW5hbFxuICAgKiB2YWx1ZXMuIFByZXBhcmVkIGJ5dGVzIHN1cnZpdmUgZnJlc2ggcmVwbGF5IFZNczsgb2JqZWN0IGdyYXBocyBkbyBub3QuXG4gICAqL1xuICByZXBsYXlQYXlsb2FkQ2FjaGU6IFJlcGxheVBheWxvYWRDYWNoZTtcbn1cblxuLyoqIFRoZSBraW5kIG9mIGJyYW5jaC1kZWNpZGluZyBkZWxpdmVyeSBhIGJhcnJpZXIgcmVwcmVzZW50cy4gKi9cbmV4cG9ydCB0eXBlIERlbGl2ZXJ5S2luZCA9ICdob29rJyB8ICd3YWl0JyB8ICdzdGVwJztcblxuaW50ZXJmYWNlIERlbGl2ZXJ5QmFycmllckVudHJ5IHtcbiAga2luZDogRGVsaXZlcnlLaW5kO1xuICAvKiogUmVzb2x2ZXMgb25jZSB0aGlzIGRlbGl2ZXJ5IGhhcyByZXNvbHZlZCB0byB0aGUgd29ya2Zsb3cuICovXG4gIGRlbGl2ZXJlZDogUHJvbWlzZTx2b2lkPjtcbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhpcyBkZWxpdmVyeSBpcyBjb21taXR0ZWQgdG8gcmVhY2hpbmcgdGhlIHdvcmtmbG93IHdpdGhvdXQgYW55XG4gICAqIGZ1cnRoZXIgYWN0aW9uIGJ5IHdvcmtmbG93IGNvZGUuIFRydWUgZm9yIHdhaXQgY29tcGxldGlvbnMgYW5kIHN0ZXBcbiAgICogcmVzdWx0cywgd2hpY2ggYWx3YXlzIHJlc29sdmUgZnJvbSB0aGVpciBvd24gY2hhaW4sIGFuZCBmb3IgYSBob29rIHBheWxvYWRcbiAgICogdGhhdCBhbHJlYWR5IGhhZCBhIHdhaXRpbmcgY29uc3VtZXIgd2hlbiBpdCB3YXMgY29uc3VtZWQuXG4gICAqXG4gICAqIEZhbHNlIGZvciBhIEJVRkZFUkVEIGhvb2sgcGF5bG9hZCBubyBjb25zdW1lciBoYXMgY2xhaW1lZCB5ZXQ6IGl0IGlzXG4gICAqIGRlbGl2ZXJlZCBieSBgY2xhaW0oKWAsIGkuZS4gd2hlbmV2ZXIgdGhlIHdvcmtmbG93IG5leHQgcmVhZHMgdGhlIGhvb2sg4oCUXG4gICAqIHdoaWNoIG1heSBiZSBjYXVzYWxseSAqYWZ0ZXIqIGEgbGF0ZXItaW4tbG9nIGRlbGl2ZXJ5LiBgYXJtKClgIGZsaXBzIGl0XG4gICAqIG9uY2UgYSBjb25zdW1lciB0YWtlcyB0aGUgcGF5bG9hZC5cbiAgICovXG4gIGFybWVkOiBib29sZWFuO1xuICAvKipcbiAgICogUmV0aXJlIHRoaXMgZW50cnk6IHJlc29sdmUgYGRlbGl2ZXJlZGAgYW5kIHJlbW92ZSBpdCBmcm9tIHRoZSByZWdpc3RyeSxcbiAgICogZXhhY3RseSBhcyBgbWFya0RlbGl2ZXJlZGAgd291bGQuIENhbGxlZCBvbmx5IGJ5IHRoZSBjb250ZXh0J3Mgc2FmZXR5LW5ldFxuICAgKiBkaXNwZW5zZXIgKHtAbGluayBlbnN1cmVCYXJyaWVyU2FmZXR5TmV0fSksIGFuZCBvbmx5IG9uIHRoZSBsb3dlc3QtaW5kZXhcbiAgICogZW50cnkgYXQgZGVsaXZlcnkgaWRsZS4gSWRlbXBvdGVudC5cbiAgICovXG4gIHJldGlyZTogKCkgPT4gdm9pZDtcbn1cblxuLyoqXG4gKiBXaGljaCBlYXJsaWVyIGtpbmRzIGVhY2ggZGVsaXZlcnkga2luZCBkZWZlcnMgYmVoaW5kLiBDaG9zZW4gc28gdGhhdCBubyBraW5kXG4gKiBibG9ja3Mgb24gYSBwZWVyIGl0IGRvZXMgbm90IG5lZWQgdG86XG4gKlxuICogIC0gYSBob29rIGRlZmVycyBiZWhpbmQgZWFybGllciBIT09LUywgV0FJVFMgYW5kIFNURVBTO1xuICogIC0gYSB3YWl0IGRlZmVycyBiZWhpbmQgZWFybGllciBIT09LUyBhbmQgU1RFUFMg4oCUIG5vdCBlYXJsaWVyIHdhaXRzLCBzaW5jZSBhXG4gKiAgICB3YWl0IG5ldmVyIG5lZWRzIHRvIHF1ZXVlIGJlaGluZCBhbm90aGVyIHdhaXQ7XG4gKiAgLSBhIHN0ZXAgZGVmZXJzIGJlaGluZCBlYXJsaWVyIFdBSVRTLCBIT09LUyBhbmQgU1RFUFMuXG4gKlxuICogVGhlIHN0ZXAtYmVoaW5kLXN0ZXAgZWRnZSBpcyBub3QgcmVkdW5kYW50IHdpdGggdGhlIHNlcmlhbCBgcHJvbWlzZVF1ZXVlYC5cbiAqIFRoZSBxdWV1ZSBmaXhlcyB0aGUgb3JkZXIgaW4gd2hpY2ggc3RlcCByZXN1bHRzIGFyZSBIWURSQVRFRCwgYnV0IGEgc3RlcCBub1xuICogbG9uZ2VyIHJlc29sdmVzIGluc2lkZSBpdHMgcXVldWUgc2xvdCDigJQgaXQgY2FwdHVyZXMgdGhlIG91dGNvbWUgdGhlcmUgYW5kXG4gKiByZXNvbHZlcyBmcm9tIGEgZGV0YWNoZWQgY29udGludWF0aW9uIG9uY2UgaXRzIGJhcnJpZXIgY2xlYXJzLiBUd28gc3RlcHNcbiAqIGFncmVlIG9uIHRoYXQgY29udGludWF0aW9uJ3Mgb3JkZXJpbmcgb25seSB3aGlsZSB0aGV5IGRlZmVyIGJlaGluZCB0aGUgc2FtZVxuICogc2V0LCB3aGljaCBob2xkcyB3aGVuIHRoZXkgYXJlIGNvbnN1bWVkIGluIHRoZSBzYW1lIGRyYWluIHdpbmRvdyBidXQgbm90XG4gKiBhY3Jvc3Mgd2luZG93czogYSBzdGVwIGNvbnN1bWVkIGxhdGVyIGNhbiBtaXNzIGEgd2FpdC9ob29rIGJhcnJpZXIgdGhhdCBhblxuICogZWFybGllciBzdGVwIGlzIHN0aWxsIHBhcmtlZCBvbiwgYmVjYXVzZSB0aGUgYmFycmllciByZXRpcmVkIGluIGJldHdlZW4uIFRoZVxuICogZWFybGllciBzdGVwIGlzIHRoZW4gd2FpdGluZyBvdXQgdGhlIG1hY3JvdGFzayB5aWVsZCBiZWxvdyB3aGlsZSB0aGUgbGF0ZXJcbiAqIG9uZSByZXNvbHZlcyBvbiBtaWNyb3Rhc2tzLCBhbmQgb3ZlcnRha2VzIGl0IOKAlCBzZWVcbiAqIGBkZWxpdmVyeS1iYXJyaWVyLWNvdmVyYWdlLnRlc3QudHNgLiBEZWZlcnJpbmcgYmVoaW5kIGVhcmxpZXIgc3RlcHNcbiAqIGNsb3NlcyB0aGF0IHdpbmRvdyBzdHJ1Y3R1cmFsbHk6IHRoZSBlYXJsaWVyIHN0ZXAncyBiYXJyaWVyIGlzIHN0aWxsXG4gKiByZWdpc3RlcmVkIHByZWNpc2VseSBiZWNhdXNlIGl0IGhhcyBub3QgZGVsaXZlcmVkIHlldC5cbiAqXG4gKiBFdmVyeSBlZGdlIHBvaW50cyBmcm9tIGEgbGF0ZXIgbG9nIGluZGV4IHRvIGEgc3RyaWN0bHkgZWFybGllciBvbmUsIHNvIHRoZVxuICogd2FpdC1mb3IgZ3JhcGggY2FuIG5ldmVyIGNvbnRhaW4gYSBjeWNsZS5cbiAqL1xuY29uc3QgREVGRVJfQkVISU5EOiBSZWNvcmQ8RGVsaXZlcnlLaW5kLCByZWFkb25seSBEZWxpdmVyeUtpbmRbXT4gPSB7XG4gIGhvb2s6IFsnaG9vaycsICd3YWl0JywgJ3N0ZXAnXSxcbiAgd2FpdDogWydob29rJywgJ3N0ZXAnXSxcbiAgc3RlcDogWyd3YWl0JywgJ2hvb2snLCAnc3RlcCddLFxufTtcblxuLyoqXG4gKiBXaGV0aGVyIGEgZGVsaXZlcnkgb2YgYGtpbmRgIGF0IGxvZyBpbmRleCBgaW5kZXhgIGdhdGVzIG9uIHRoZSBlYXJsaWVyXG4gKiByZWdpc3RyeSBlbnRyeSBgb3RoZXJgIChhdCBgb3RoZXJJbmRleGApLlxuICpcbiAqIFNpbmdsZSBzb3VyY2Ugb2YgdHJ1dGggZm9yIHRoYXQgcXVlc3Rpb24sIGNhbGxlZCBieSBib3RoXG4gKiB7QGxpbmsgYXdhaXRFYXJsaWVyRGVsaXZlcmllc30gKHdoaWNoIGF3YWl0cyB3aGF0IGl0IGdhdGVzIG9uKSBhbmRcbiAqIHtAbGluayBjb21wdXRlUmVzb2x2ZXNPbkl0c093bn0gKHdoaWNoIHJlY3Vyc2VzIGludG8gd2hhdCBpdCBnYXRlcyBvbikuXG4gKiBUaG9zZSB0d28gTVVTVCBhZ3JlZSBleGFjdGx5LCBhbmQgdGhlIGRvYyBibG9jayBvblxuICoge0BsaW5rIGF3YWl0RWFybGllckRlbGl2ZXJpZXN9IHN0YWtlcyBkZWFkbG9jay1mcmVlZG9tIG9uIGl0LCBzbyB0aGVcbiAqIGNvbmRpdGlvbiBsaXZlcyBoZXJlIHJhdGhlciB0aGFuIGJlaW5nIHNwZWxsZWQgb3V0IHR3aWNlLlxuICovXG5mdW5jdGlvbiBnYXRlc09uKFxuICBraW5kOiBEZWxpdmVyeUtpbmQsXG4gIGluZGV4OiBudW1iZXIsXG4gIG90aGVySW5kZXg6IG51bWJlcixcbiAgb3RoZXI6IERlbGl2ZXJ5QmFycmllckVudHJ5XG4pOiBib29sZWFuIHtcbiAgaWYgKG90aGVySW5kZXggPj0gaW5kZXggfHwgIURFRkVSX0JFSElORFtraW5kXS5pbmNsdWRlcyhvdGhlci5raW5kKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICAvLyBBIHN0ZXAgc2tpcHMgYW4gVU5BUk1FRCBlYXJsaWVyIGVudHJ5IChhbiB1bmNsYWltZWQgYnVmZmVyZWQgaG9va1xuICAvLyBwYXlsb2FkKSDigJQgc2VlIHRoZSBhc3ltbWV0cnkgZGVzY3JpYmVkIG9uIGBhd2FpdEVhcmxpZXJEZWxpdmVyaWVzYC4gVGhlXG4gIC8vIHNraXAgaXMgZGlyZWN0LCBuZXZlciB0cmFuc2l0aXZlOiBhcm1lZCBlbnRyaWVzIGFyZSBzdGlsbCBnYXRlZCBvbiwgZXZlblxuICAvLyB3aGVuIHRoZXkgYXJlIHRoZW1zZWx2ZXMgcGFya2VkIGJlaGluZCBzdWNoIGEgcGF5bG9hZC5cbiAgcmV0dXJuICEoa2luZCA9PT0gJ3N0ZXAnICYmICFvdGhlci5hcm1lZCk7XG59XG5cbi8qKlxuICogV2hldGhlciBgZW50cnlgIHdpbGwgcmVzb2x2ZSBvbiBpdHMgb3duIOKAlCBpdCBpcyBhcm1lZCwgYW5kIGV2ZXJ5IGVhcmxpZXJcbiAqIGRlbGl2ZXJ5IGl0IGFjdHVhbGx5IGdhdGVzIG9uICh7QGxpbmsgZ2F0ZXNPbn0pIHdpbGwgbGlrZXdpc2UgcmVzb2x2ZSBvbiBpdHNcbiAqIG93bi5cbiAqXG4gKiBBIHN0ZXAgZG9lcyBub3QgZ2F0ZSBvbiBhbiB1bmNsYWltZWQgYnVmZmVyZWQgcGF5bG9hZCwgc28gc3VjaCBhIHBheWxvYWRcbiAqIGNhbm5vdCBrZWVwIGl0IGZyb20gcmVzb2x2aW5nLiBBIHN0ZXAgRE9FUyBnYXRlIG9uIGVhcmxpZXIgYXJtZWQgd2FpdHMgYW5kXG4gKiBob29rcywgc28gb25lIHBhcmtlZCBiZWhpbmQgYW4gdW5jbGFpbWVkIHBheWxvYWQgbWFrZXMgdGhlIHN0ZXBcbiAqIG5vbi1zZWxmLXJlc29sdmluZyBpbiB0dXJuLiBEaXNhZ3JlZWluZyB3aXRoIHtAbGluayBhd2FpdEVhcmxpZXJEZWxpdmVyaWVzfVxuICogaGVyZSB3b3VsZCBub3QgYmUgYSBjb3NtZXRpYyBwcm9ibGVtOiB0aGlzIHByZWRpY2F0ZSBpcyB3aGF0XG4gKiB7QGxpbmsgaGFzUGFya2VkQ29tbWl0dGVkRGVsaXZlcnl9IHVzZXMgdG8gZGVjaWRlIHdoZXRoZXIgaWRsZSBpcyByZWFjaGFibGUsXG4gKiBhbmQgYW4gZW50cnkgcmVwb3J0ZWQgc2VsZi1yZXNvbHZpbmcgd2hpbGUgaXQgaXMgaW4gZmFjdCBwYXJrZWQgYmVoaW5kIGFcbiAqIHBheWxvYWQgdGhhdCBvbmx5IHRoZSBpZGxlIHNhZmV0eSBuZXQgY2FuIHJldGlyZSB3b3VsZCBnYXRlIGl0cyBvd25cbiAqIHJldGlyZW1lbnQuXG4gKlxuICogUmVjdXJzaW9uIHRlcm1pbmF0ZXMgYmVjYXVzZSBldmVyeSBlZGdlIHBvaW50cyB0byBhIHN0cmljdGx5IHNtYWxsZXIgaW5kZXguXG4gKiBgbWVtb2Aga2VlcHMgdGhlIHdhbGsgbGluZWFyIGluIHJlZ2lzdHJ5IHNpemUsIGFuZCB0aGUgcmVnaXN0cnkgaXMgbm90IHNtYWxsXG4gKiBieSBjb25zdHJ1Y3Rpb24g4oCUIGBFdmVudHNDb25zdW1lcmAgZHJhaW5zIGNvbnNlY3V0aXZlbHkgY29uc3VtYWJsZSBldmVudHNcbiAqIHN5bmNocm9ub3VzbHkgd2hpbGUgYmFycmllcnMgb25seSByZXRpcmUgb24gbWljcm90YXNrLWRyaXZlbiBkZWxpdmVyaWVzLCBzb1xuICogYSBmYW4tb3V0IG9mIGBQcm9taXNlLnJhY2UoW2hvb2ssIHNsZWVwXSlgIGJyYW5jaGVzIGFjY3VtdWxhdGVzIG9uZSBiYXJyaWVyXG4gKiBwZXIgYnJhbmNoIHBlciBraW5kLiBUaGUgbWVtbyBNVVNUIGJlIHBlci1jYWxsOiBgYXJtZWRgIG11dGF0ZXMgYmV0d2VlblxuICogY2FsbHMgYXMgYnVmZmVyZWQgcGF5bG9hZHMgYXJlIGNsYWltZWQuXG4gKlxuICogVGhlIG1lbW8gaXMgYW4gb3B0aW1pemF0aW9uLCBub3QgYSBjb3JyZWN0bmVzcyByZXF1aXJlbWVudC4gSXQgb25jZSB3YXMgb25lOlxuICogYGF3YWl0RWFybGllckRlbGl2ZXJpZXNgIHVzZWQgdG8gcnVuIHRoaXMgd2FsayBmb3IgZXZlcnkgZWFybGllciBlbnRyeSBvZiBhXG4gKiBzdGVwIGRlbGl2ZXJ5LCB3aXRoIG5vIGVhcmx5IGV4aXQsIHdoaWNoIHVubWVtb2l6ZWQgaXMgVChuKSA9IM6jIFQoaikg4oCUXG4gKiBtZWFzdXJlZCBhdCA0LjNlOCByZWN1cnNpdmUgY2FsbHMgKDg0cykgZm9yIDQwIGFsdGVybmF0aW5nIGFybWVkIGhvb2svd2FpdFxuICogYmFycmllcnMuIFRoYXQgY2FsbCBzaXRlIGlzIGdvbmU7IGEgc3RlcCBub3cgdGVzdHMgYGFybWVkYCBkaXJlY3RseS4gVGhlIG9uZVxuICogc3Vydml2aW5nIGNhbGxlciwge0BsaW5rIGhhc1BhcmtlZENvbW1pdHRlZERlbGl2ZXJ5fSwgY2Fubm90IHJlYWNoIHRoYXRcbiAqIHNoYXBlOiBpdCByZXR1cm5zIGF0IHRoZSBGSVJTVCBzZWxmLXJlc29sdmluZyBlbnRyeSwgc28gaXQgb25seSBldmVyXG4gKiBhZHZhbmNlcyBwYXN0IGVudHJpZXMgdGhhdCBhcmUgbm9uLXNlbGYtcmVzb2x2aW5nLCBhbmQgdGhvc2Ugc2hvcnQtY2lyY3VpdFxuICogb24gdGhlaXIgZmlyc3QgZmFsc2UgY2hpbGQuIEV2ZXJ5IGVudHJ5IGl0IGV2YWx1YXRlcyB0aGVyZWZvcmUgaGFzXG4gKiBhbGwtZmFsc2UgcHJlZGVjZXNzb3JzIGFuZCByZXR1cm5zIGFmdGVyIG9uZSBjaGlsZCwgZGVnZW5lcmF0aW5nIHRoZSB3YWxrIHRvXG4gKiBhIGNoYWluIChtZWFzdXJlZDogOTggY2FsbHMgdW5tZW1vaXplZCBmb3IgdGhlIHdvcnN0IDQwLWJhcnJpZXIgc2hhcGUsIDFcbiAqIGNhbGwgZm9yIHRoZSByZWdpc3RyeSBhYm92ZSkuIERvIG5vdCByZXN0b3JlIGFuIGV4cG9uZW50aWFsIGNsYWltIGhlcmVcbiAqIHdpdGhvdXQgcmVzdG9yaW5nIGEgY2FsbGVyIHRoYXQgY2FuIHByb2R1Y2UgaXQuXG4gKi9cbmZ1bmN0aW9uIHJlc29sdmVzT25JdHNPd24oXG4gIGJhcnJpZXJzOiBNYXA8bnVtYmVyLCBEZWxpdmVyeUJhcnJpZXJFbnRyeT4sXG4gIGluZGV4OiBudW1iZXIsXG4gIGVudHJ5OiBEZWxpdmVyeUJhcnJpZXJFbnRyeSxcbiAgbWVtbzogTWFwPG51bWJlciwgYm9vbGVhbj5cbik6IGJvb2xlYW4ge1xuICBjb25zdCBjYWNoZWQgPSBtZW1vLmdldChpbmRleCk7XG4gIGlmIChjYWNoZWQgIT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiBjYWNoZWQ7XG4gIH1cbiAgY29uc3QgcmVzdWx0ID0gY29tcHV0ZVJlc29sdmVzT25JdHNPd24oYmFycmllcnMsIGluZGV4LCBlbnRyeSwgbWVtbyk7XG4gIG1lbW8uc2V0KGluZGV4LCByZXN1bHQpO1xuICByZXR1cm4gcmVzdWx0O1xufVxuXG5mdW5jdGlvbiBjb21wdXRlUmVzb2x2ZXNPbkl0c093bihcbiAgYmFycmllcnM6IE1hcDxudW1iZXIsIERlbGl2ZXJ5QmFycmllckVudHJ5PixcbiAgaW5kZXg6IG51bWJlcixcbiAgZW50cnk6IERlbGl2ZXJ5QmFycmllckVudHJ5LFxuICBtZW1vOiBNYXA8bnVtYmVyLCBib29sZWFuPlxuKTogYm9vbGVhbiB7XG4gIGlmICghZW50cnkuYXJtZWQpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgZm9yIChjb25zdCBbb3RoZXJJbmRleCwgb3RoZXJdIG9mIGJhcnJpZXJzKSB7XG4gICAgaWYgKCFnYXRlc09uKGVudHJ5LmtpbmQsIGluZGV4LCBvdGhlckluZGV4LCBvdGhlcikpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBpZiAoIXJlc29sdmVzT25JdHNPd24oYmFycmllcnMsIG90aGVySW5kZXgsIG90aGVyLCBtZW1vKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdHJ1ZTtcbn1cblxuLyoqXG4gKiBBd2FpdHMsIGluIHN0cmljdCBldmVudC1sb2cgb3JkZXIsIGV2ZXJ5IHN0aWxsLXJlZ2lzdGVyZWQgZGVsaXZlcnkgdGhhdCBpc1xuICogZWFybGllciBpbiB0aGUgbG9nIHRoYW4gYGV2ZW50SW5kZXhgIGFuZCB0aGF0IGEgZGVsaXZlcnkgb2YgYGtpbmRgIGRlZmVyc1xuICogYmVoaW5kIChzZWUge0BsaW5rIERFRkVSX0JFSElORH0pLCBzbyB0aGF0IHRoaXMgcmVzb2x1dGlvbiBpcyBoYW5kZWQgdG8gdGhlXG4gKiB3b3JrZmxvdyBvbmx5IGFmdGVyIGFsbCByZWxldmFudCBlYXJsaWVyLWluLWxvZyBkZWxpdmVyaWVzIGhhdmUgYmVlbi4gVGhpc1xuICogaXMgd2hhdCBrZWVwcyBhIGBQcm9taXNlLnJhY2VgIOKAlCBvciB0aGUgVUxJRCBhIGZvbGxvdy11cCBgdXNlU3RlcGAgZHJhd3Mgb25cbiAqIGEgY29uY3VycmVudCBicmFuY2gg4oCUIGRldGVybWluaXN0aWMgYW5kIGFsaWduZWQgd2l0aCB0aGUgY29tbWl0dGVkIGV2ZW50XG4gKiBsb2csIGluZGVwZW5kZW50IG9mIG1pY3JvdGFzay1ob3AgY291bnRzLCBoeWRyYXRpb24gdGltZSwgb3IgcmFjZS1hcmd1bWVudFxuICogb3JkZXIuIFdoZW4gdGhpcyBkZWxpdmVyeSBkb2VzIGhhdmUgdG8gd2FpdCwgaXQgYWxzbyB5aWVsZHMgYSBtYWNyb3Rhc2tcbiAqIGFmdGVyd2FyZHMgc28gdGhlIGVhcmxpZXIgZGVsaXZlcnkncyBjb25zdW1lciBjYW4gcnVuIHRvIGl0cyBvd24gbmV4dFxuICogc3VzcGVuc2lvbiBwb2ludCBmaXJzdDsgc2VlIHRoZSBjb21tZW50IGF0IHRoYXQgYGF3YWl0YCBmb3Igd2h5IG9yZGVyaW5nIHRoZVxuICogYHJlc29sdmUoKWAgY2FsbHMgYWxvbmUgaXMgbm90IGVub3VnaC5cbiAqXG4gKiBXaGF0IGNvdW50cyBhcyBcImRlZmVycyBiZWhpbmRcIiBpcyB7QGxpbmsgZ2F0ZXNPbn0sIHNoYXJlZCB3aXRoXG4gKiB7QGxpbmsgY29tcHV0ZVJlc29sdmVzT25JdHNPd259IHNvIHRoZSB0d28gY2Fubm90IGRyaWZ0LlxuICpcbiAqIE9uZSBhc3ltbWV0cnk6IGEgU1RFUCByZXN1bHQgc2tpcHMgYW55IGVhcmxpZXIgZGVsaXZlcnkgdGhhdCBpcyBVTkFSTUVELFxuICogaS5lLiBhIGJ1ZmZlcmVkIGhvb2sgcGF5bG9hZCBubyBjb25zdW1lciBoYXMgY2xhaW1lZC4gU3VjaCBhIHBheWxvYWQgaXNcbiAqIGRlbGl2ZXJlZCBvbmx5IHdoZW4gdGhlIHdvcmtmbG93IG5leHQgcmVhZHMgdGhlIGhvb2ssIGFuZCByZWFjaGluZyB0aGF0IHJlYWRcbiAqIHZlcnkgY29tbW9ubHkgcmVxdWlyZXMgdGhlIHN0ZXAgcmVzdWx0IGl0c2VsZiAoYGF3YWl0IHN0ZXBYKClgIGJlZm9yZSB0aGVcbiAqIHJlYWQpLiBHYXRpbmcgdGhlIHN0ZXAgb24gaXQgd291bGQgc3RhbGwgdGhlIHdvcmtmbG93IHVudGlsIHRoZSBiYXJyaWVyJ3NcbiAqIGlkbGUgc2FmZXR5IG5ldCBmaXJlcywgd2hpY2ggdGhlbiByZWxlYXNlcyBldmVyeSBkZWxpdmVyeSBxdWV1ZWQgYmVoaW5kIHRoYXRcbiAqIHBheWxvYWQgYXQgb25jZSDigJQgbG9zaW5nIGV4YWN0bHkgdGhlIHJhY2UgdGhpcyBvcmRlcmluZyBleGlzdHMgdG8gcHJvdGVjdC5cbiAqIFdhaXRzIGFuZCBob29rcyBrZWVwIGdhdGluZyBvbiB1bmNsYWltZWQgcGF5bG9hZHM6IGZvciB0aGVtLCB3YWl0aW5nIGZvciB0aGVcbiAqIGNsYWltIElTIHRoZSBvcmRlcmluZyBndWFyYW50ZWUgKGEgYHdhaXRfY29tcGxldGVkYCBtdXN0IG5vdCBwcmVlbXB0IGFcbiAqIHBheWxvYWQgdGhlIGxvZyBvcmRlcmVkIGZpcnN0KS5cbiAqXG4gKiBUaGUgc2tpcCBpcyBkaXJlY3QsIG5ldmVyIHRyYW5zaXRpdmUuIEEgc3RlcCBzdGlsbCBnYXRlcyBvbiBhbiBlYXJsaWVyIEFSTUVEXG4gKiB3YWl0IG9yIGhvb2ssIGluY2x1ZGluZyBvbmUgdGhhdCBpcyBpdHNlbGYgcGFya2VkIGJlaGluZCBhbiB1bmNsYWltZWRcbiAqIHBheWxvYWQuIFNraXBwaW5nIHRob3NlIHRvbyB3b3VsZCBpbnZlcnQgbG9nIG9yZGVyIGZvciB0aGUgY29tbW9uZXN0IHNoYXBlXG4gKiB0aGVyZSBpczogYSB3b3JrZmxvdyB0aGF0IGNyZWF0ZXMgYSBob29rIGl0IGRvZXMgbm90IHJlYWQgb24gdGhpcyBicmFuY2gsXG4gKiByYWNlcyBgc3RlcGAgYWdhaW5zdCBgc2xlZXBgLCBhbmQgaGFzIHRoZSBsb2cgc2F5IHRoZSBzbGVlcCB3b24uIFRoZSBzdGVwXG4gKiB3b3VsZCB0aGVuIG92ZXJ0YWtlIHRoZSB3YWl0LCBib3RoIGJyYW5jaGVzIHdvdWxkIHN3YXAgdGhlIGNvcnJlbGF0aW9uIGlkc1xuICogdGhleSBkcmF3IG5leHQsIGFuZCByZXBsYXkgd291bGQgZGl2ZXJnZSDigJQgc2VlXG4gKiBgc3RlcC1kZWxpdmVyeS1vcmRlcmluZy50ZXN0LnRzYC4gV2FpdGluZyBpbnN0ZWFkIGlzIHNhZmUgYmVjYXVzZSB0aGVcbiAqIHBheWxvYWQncyBvd24gaWRsZSBzYWZldHkgbmV0IHJldGlyZXMgaXQgYW5kIHRoZSB3aG9sZSBjaGFpbiB0aGVuIGRlbGl2ZXJzXG4gKiBpbiBsb2cgb3JkZXI7IHtAbGluayBoYXNQYXJrZWRDb21taXR0ZWREZWxpdmVyeX0gZGVsaWJlcmF0ZWx5IHJlcG9ydHMgc3VjaCBhXG4gKiBzdGVwIGFzIG5vdCBzZWxmLXJlc29sdmluZyBzbyB0aGF0IGlkbGUgc3RheXMgcmVhY2hhYmxlLlxuICpcbiAqIFwiVGhlIHdob2xlIGNoYWluIHRoZW4gZGVsaXZlcnMgaW4gbG9nIG9yZGVyXCIgcmVzdHMgb24gdGhlIFBBWUxPQUQncyBiYXJyaWVyXG4gKiBiZWluZyByZXRpcmVkIGJlZm9yZSB0aGF0IG9mIGFueXRoaW5nIHBhcmtlZCBiZWhpbmQgaXQuIFRoYXQgb3JkZXIgaXNcbiAqIHN0cnVjdHVyYWw6IHNhZmV0eS1uZXQgcmV0aXJlbWVudHMgZ28gdGhyb3VnaCBvbmUgcGVyLWNvbnRleHQgZGlzcGVuc2VyIHRoYXRcbiAqIG9ubHkgZXZlciByZXRpcmVzIHRoZSBsb3dlc3QtaW5kZXggZW50cnkgYXQgZGVsaXZlcnkgaWRsZSwgYW5kIGV2ZXJ5XG4gKiByZXRpcmVtZW50IHRoYXQgd2FrZXMgYSBjaGFpbiBmbGlwcyB7QGxpbmsgaGFzUGFya2VkQ29tbWl0dGVkRGVsaXZlcnl9IGJhY2tcbiAqIHRvIHRydWUsIHJlLWJsb2NraW5nIHRoZSBkaXNwZW5zZXIgdW50aWwgdGhlIGNoYWluIGhhcyBkcmFpbmVkIOKAlCBzZWVcbiAqIHtAbGluayBlbnN1cmVCYXJyaWVyU2FmZXR5TmV0fS4gKFRoaXMgdXNlZCB0byByZXN0IG9uIHRoZSBGSUZPIG9mIG9uZSBpZGxlXG4gKiBwb2xsIHBlciBiYXJyaWVyLCB3aGljaCBoZWxkIGZvciBhIHNpbmdsZSBwYXJrZWQgc2VnbWVudCBidXQgZGVjYXllZCB0b1xuICogdGltaW5nIG5vaXNlIHdpdGggc2V2ZXJhbCDigJQgdGhlIHJlbGVhc2Ugb3JkZXIsIGFuZCB0aGVyZWZvcmUgdGhlIFVMSURzXG4gKiBkcmF3biBieSB0aGUgd29rZW4gYnJhbmNoZXMsIHRoZW4gZGVwZW5kZWQgb24gaG93IG11Y2ggbG9nIHRoZSByZXBsYXkgaGFkXG4gKiBsb2FkZWQuIHN0b3JtLWxvZy1yZXBsYXkudGVzdC50cyByZXBsYXlzIGEgcHJvZHVjdGlvbiBsb2cgY29ycnVwdGVkIGV4YWN0bHlcbiAqIHRoYXQgd2F5LilcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGF3YWl0RWFybGllckRlbGl2ZXJpZXMoXG4gIGN0eDogV29ya2Zsb3dPcmNoZXN0cmF0b3JDb250ZXh0LFxuICBldmVudEluZGV4OiBudW1iZXIgfCB1bmRlZmluZWQsXG4gIGtpbmQ6IERlbGl2ZXJ5S2luZFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIC8vIERlZmVuc2l2ZTogdG9sZXJhdGUgY29udGV4dHMgdGhhdCBwcmVkYXRlIHRoaXMgZmllbGQgKHRlc3QgaGFybmVzc2VzKS5cbiAgaWYgKFxuICAgIGV2ZW50SW5kZXggPT09IHVuZGVmaW5lZCB8fFxuICAgICFjdHgucGVuZGluZ0RlbGl2ZXJ5QmFycmllcnMgfHxcbiAgICBjdHgucGVuZGluZ0RlbGl2ZXJ5QmFycmllcnMuc2l6ZSA9PT0gMFxuICApIHtcbiAgICByZXR1cm47XG4gIH1cbiAgY29uc3QgYmFycmllcnMgPSBjdHgucGVuZGluZ0RlbGl2ZXJ5QmFycmllcnM7XG4gIGNvbnN0IGVhcmxpZXI6IFByb21pc2U8dm9pZD5bXSA9IFtdO1xuICBmb3IgKGNvbnN0IFtpbmRleCwgZW50cnldIG9mIGJhcnJpZXJzKSB7XG4gICAgaWYgKCFnYXRlc09uKGtpbmQsIGV2ZW50SW5kZXgsIGluZGV4LCBlbnRyeSkpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBlYXJsaWVyLnB1c2goZW50cnkuZGVsaXZlcmVkKTtcbiAgfVxuICBpZiAoZWFybGllci5sZW5ndGggPiAwKSB7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoZWFybGllcik7XG4gICAgLy8gQW4gZWFybGllciBkZWxpdmVyeSBiZWluZyBcImRlbGl2ZXJlZFwiIG9ubHkgbWVhbnMgaXRzIGByZXNvbHZlKClgIHJhbi5cbiAgICAvLyBUaGUgYnJhbmNoIGl0IHdva2UgbWF5IG5lZWQgYW4gYXJiaXRyYXJ5IG51bWJlciBvZiBmdXJ0aGVyIG1pY3JvdGFza1xuICAgIC8vIGhvcHMgYmVmb3JlIGl0IHJlYWNoZXMgaXRzIG5leHQgYHVzZVN0ZXBgIGNhbGwgYW5kIGRyYXdzIGEgVUxJRCDigJQgYVxuICAgIC8vIGBmb3IgYXdhaXRgIG92ZXIgYSBob29rLCBmb3IgaW5zdGFuY2UsIHJlc3VtZXMgdGhlIGdlbmVyYXRvciwgc2V0dGxlc1xuICAgIC8vIHRoZSBwcm9taXNlIGZyb20gYG5leHQoKWAsIGFuZCBvbmx5IHRoZW4gcnVucyB0aGUgbG9vcCBib2R5LiBSZXNvbHZpbmdcbiAgICAvLyB0aGlzIGRlbGl2ZXJ5IG9uIGEgbWljcm90YXNrIHdvdWxkIGxldCBpdCBvdmVydGFrZSB0aGF0IGJyYW5jaCBhbmRcbiAgICAvLyByZW9yZGVyIHRoZSBVTElEIGFsbG9jYXRpb24gYW55d2F5LCB0dXJuaW5nIHRoZSBndWFyYW50ZWUgYmVsb3cgaW50byBhXG4gICAgLy8gaG9wLWNvdW50IHJhY2UgdGhhdCBob2xkcyBvbmx5IGZvciB0aGUgc2hvcnRlc3QgY29uc3VtZXJzLlxuICAgIC8vXG4gICAgLy8gWWllbGRpbmcgYSBtYWNyb3Rhc2sgbGV0cyB0aGUgZWFybGllciBicmFuY2gncyBlbnRpcmUgbWljcm90YXNrIGNoYWluXG4gICAgLy8gZHJhaW4gZmlyc3QsIHdoYXRldmVyIGl0cyBsZW5ndGgsIHNvIGxvZyBvcmRlciBzdXJ2aXZlcyByZWdhcmRsZXNzIG9mXG4gICAgLy8gaG93IHRoZSB3b3JrZmxvdyBjb25zdW1lcyB0aGUgZWFybGllciBkZWxpdmVyeS4gT25seSBkZWxpdmVyaWVzIHRoYXRcbiAgICAvLyBhY3R1YWxseSBoYWQgdG8gZGVmZXIgcGF5IHRoaXMsIHNvIHRoZSBjb21tb24gc2luZ2xlLWRlbGl2ZXJ5IGRyYWluIGlzXG4gICAgLy8gdW5hZmZlY3RlZC5cbiAgICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCAwKSk7XG4gIH1cbn1cblxuLyoqIEhhbmRsZSBmb3IgYSByZWdpc3RlcmVkIGJyYW5jaC1kZWNpZGluZyBkZWxpdmVyeSBiYXJyaWVyLiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZWxpdmVyeUJhcnJpZXIge1xuICAvKipcbiAgICogTWFyayB0aGlzIGRlbGl2ZXJ5IGFzIGRlbGl2ZXJlZCB0byB0aGUgd29ya2Zsb3cuIFJlc29sdmVzIGl0c1xuICAgKiBgZGVsaXZlcmVkYCBwcm9taXNlIHNvIGFueSBsYXRlci1pbi1sb2cgZGVsaXZlcnkgZ2F0ZWQgb24gaXQgKHZpYVxuICAgKiB7QGxpbmsgYXdhaXRFYXJsaWVyRGVsaXZlcmllc30pIG1heSBwcm9jZWVkLCBhbmQgcmVtb3ZlcyBpdCBmcm9tIHRoZVxuICAgKiByZWdpc3RyeS4gSWRlbXBvdGVudC5cbiAgICovXG4gIG1hcmtEZWxpdmVyZWQ6ICgpID0+IHZvaWQ7XG4gIC8qKlxuICAgKiBNYXJrIHRoaXMgZGVsaXZlcnkgYXMgY29tbWl0dGVkIHRvIGhhcHBlbmluZywgZm9yIGEgYmFycmllciByZWdpc3RlcmVkXG4gICAqIHVuYXJtZWQgKGEgYnVmZmVyZWQgaG9vayBwYXlsb2FkKSBvbmNlIGEgY29uc3VtZXIgaGFzIGNsYWltZWQgaXQuIEZyb21cbiAgICogdGhlbiBvbiBhIGxhdGVyIHN0ZXAgcmVzdWx0IG1heSBiZSBvcmRlcmVkIGJlaGluZCBpdC4gSWRlbXBvdGVudC5cbiAgICovXG4gIGFybTogKCkgPT4gdm9pZDtcbn1cblxuLyoqXG4gKiBSZWdpc3RlciBhIGJyYW5jaC1kZWNpZGluZyBkZWxpdmVyeSBhdCBpdHMgZXZlbnQtbG9nIGluZGV4IHNvIHRoYXQgbGF0ZXJcbiAqIGRlbGl2ZXJpZXMgY2FuIGJlIG9yZGVyZWQgc3RyaWN0bHkgYWZ0ZXIgaXQuIFJldHVybnMgYW4gaW5lcnQgaGFuZGxlIHdoZW5cbiAqIGBwZW5kaW5nRGVsaXZlcnlCYXJyaWVyc2AgaXMgbm90IGluaXRpYWxpemVkLlxuICpcbiAqIFBhc3MgYGFybWVkOiBmYWxzZWAgZm9yIGEgZGVsaXZlcnkgd2hvc2UgcmVzb2x1dGlvbiB3YWl0cyBvbiB3b3JrZmxvdyBjb2RlXG4gKiBhc2tpbmcgZm9yIGl0IChhIGJ1ZmZlcmVkIGhvb2sgcGF5bG9hZCk7IGNhbGwgYGFybSgpYCB3aGVuIGl0IGRvZXMuXG4gKlxuICogVG8gZ3VhcmFudGVlIGEgbGF0ZXIgZGVsaXZlcnkgZ2F0ZWQgb24gdGhpcyBvbmUgY2FuIG5ldmVyIGhhbmcgd2hlbiB0aGlzXG4gKiBkZWxpdmVyeSBpcyBhYmFuZG9uZWQgKHRoZSB3b3JrZmxvdyB0b29rIGEgZGlmZmVyZW50IGJyYW5jaCBvciBpc1xuICogc3VzcGVuZGluZyBhbmQgbmV2ZXIgb2JzZXJ2ZXMgaXQpLCB0aGUgYmFycmllciBhdXRvLXJlc29sdmVzIGF0IGlkbGUuXG4gKlxuICogSU5WQVJJQU5UIHJlcXVpcmVkIG9mIGV2ZXJ5IGNhbGwgc2l0ZTogYSBiYXJyaWVyIHRoYXQgaXMgZXZlciBgYXJtZWRgIG11c3RcbiAqIGJlIHBhaXJlZCB3aXRoIGEgZGVsaXZlcnkgY2hhaW4gdGhhdCBydW5zIHVuY29uZGl0aW9uYWxseSDigJQgYXR0YWNoZWQgd2hlblxuICogdGhlIGV2ZW50IGlzIGNvbnN1bWVkICh3YWl0cywgc3RlcCByZXN1bHRzLCB3YWl0aW5nLWNvbnN1bWVyIGhvb2sgcGF5bG9hZHMsXG4gKiBhYm9ydHMpLCBvciBieSB0aGUgYGNsYWltKClgIHdob3NlIGludm9jYXRpb24gaXMgd2hhdCBhcm1zIGl0IChidWZmZXJlZFxuICogaG9vayBwYXlsb2FkcykuIFRoZSBpZGxlIGNoZWNrICh7QGxpbmsgc2NoZWR1bGVXaGVuSWRsZX0pIHJlZnVzZXMgdG9cbiAqIG9ic2VydmUgaWRsZSB3aGlsZSBhbiBhcm1lZCwgc2VsZi1yZXNvbHZpbmcgYmFycmllciBpcyB1bmRlbGl2ZXJlZCwgYW5kIHRoZVxuICogc2FmZXR5IG5ldCBiZWxvdyBpcyBpdHNlbGYgaWRsZS1nYXRlZCDigJQgc28gYW4gYXJtZWQgYmFycmllciB3aXRoIG5vXG4gKiB1bmNvbmRpdGlvbmFsIGNoYWluIHdvdWxkIGxpdmVsb2NrIGV2ZXJ5IGlkbGUgY2hlY2sgaW4gdGhlIHJ1biwgaW5jbHVkaW5nXG4gKiBpdHMgb3duIHJldGlyZW1lbnQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWdpc3RlckRlbGl2ZXJ5QmFycmllcihcbiAgY3R4OiBXb3JrZmxvd09yY2hlc3RyYXRvckNvbnRleHQsXG4gIGV2ZW50SW5kZXg6IG51bWJlciB8IHVuZGVmaW5lZCxcbiAga2luZDogRGVsaXZlcnlLaW5kLFxuICBvcHRpb25zOiB7IGFybWVkPzogYm9vbGVhbiB9ID0ge31cbik6IERlbGl2ZXJ5QmFycmllciB7XG4gIGNvbnN0IGJhcnJpZXJzID0gY3R4LnBlbmRpbmdEZWxpdmVyeUJhcnJpZXJzO1xuICBpZiAoIWJhcnJpZXJzIHx8IGV2ZW50SW5kZXggPT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiB7IG1hcmtEZWxpdmVyZWQ6ICgpID0+IHt9LCBhcm06ICgpID0+IHt9IH07XG4gIH1cblxuICBsZXQgZG9uZSA9IGZhbHNlO1xuICBjb25zdCB7IHByb21pc2UsIHJlc29sdmUgfSA9IHdpdGhSZXNvbHZlcnM8dm9pZD4oKTtcblxuICBjb25zdCBmaW5pc2ggPSAoKSA9PiB7XG4gICAgaWYgKGRvbmUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZG9uZSA9IHRydWU7XG4gICAgaWYgKGJhcnJpZXJzLmdldChldmVudEluZGV4KSA9PT0gZW50cnkpIHtcbiAgICAgIGJhcnJpZXJzLmRlbGV0ZShldmVudEluZGV4KTtcbiAgICB9XG4gICAgcmVzb2x2ZSgpO1xuICB9O1xuXG4gIGNvbnN0IGVudHJ5OiBEZWxpdmVyeUJhcnJpZXJFbnRyeSA9IHtcbiAgICBraW5kLFxuICAgIGRlbGl2ZXJlZDogcHJvbWlzZSxcbiAgICBhcm1lZDogb3B0aW9ucy5hcm1lZCA/PyB0cnVlLFxuICAgIHJldGlyZTogZmluaXNoLFxuICB9O1xuICBiYXJyaWVycy5zZXQoZXZlbnRJbmRleCwgZW50cnkpO1xuXG4gIC8vIFNhZmV0eSBuZXQ6IGlmIHRoaXMgZGVsaXZlcnkgaXMgbmV2ZXIgZGVsaXZlcmVkIHRvIHRoZSB3b3JrZmxvdyAoaXRzXG4gIC8vIGJyYW5jaCB3YXMgbm90IHRha2VuIC8gdGhlIHJ1biBpcyBzdXNwZW5kaW5nLCBvciBhIGJ1ZmZlcmVkIGhvb2sgcGF5bG9hZFxuICAvLyBpcyBvbmx5IGNsYWltZWQgYWZ0ZXIgYSBsYXRlciBkZWxpdmVyeSB0aGUgd29ya2Zsb3cgaXMgc3RpbGwgd2FpdGluZyBvbiksXG4gIC8vIGl0IGlzIHJldGlyZWQgYXQgaWRsZSBzbyBhIGxhdGVyIGRlbGl2ZXJ5IGdhdGVkIG9uIGl0IGNhbm5vdCBkZWFkbG9jayBhbmRcbiAgLy8gdGhlIHJlZ2lzdHJ5IGNhbm5vdCBsZWFrIGFuIGVudHJ5IHBlciBhYmFuZG9uZWQgZGVsaXZlcnkuIFJldGlyZW1lbnQgZ29lc1xuICAvLyB0aHJvdWdoIHRoZSBjb250ZXh0J3Mgc2luZ2xlIG9yZGVyZWQgZGlzcGVuc2VyIHJhdGhlciB0aGFuIGEgcGVyLWJhcnJpZXJcbiAgLy8gaWRsZSBwb2xsIOKAlCBzZWUge0BsaW5rIGVuc3VyZUJhcnJpZXJTYWZldHlOZXR9IGZvciB3aHkgdGhlIE9SREVSIG9mIHRoZXNlXG4gIC8vIHJldGlyZW1lbnRzIGlzIGxvYWQtYmVhcmluZy5cbiAgZW5zdXJlQmFycmllclNhZmV0eU5ldChjdHgpO1xuXG4gIHJldHVybiB7XG4gICAgbWFya0RlbGl2ZXJlZDogZmluaXNoLFxuICAgIGFybTogKCkgPT4ge1xuICAgICAgZW50cnkuYXJtZWQgPSB0cnVlO1xuICAgIH0sXG4gIH07XG59XG5cbi8qKlxuICogQ29udGV4dHMgd2hvc2UgYmFycmllciBzYWZldHktbmV0IGRpc3BlbnNlciBpcyBjdXJyZW50bHkgYXJtZWQuIE1vZHVsZS1sZXZlbFxuICogc28gdGhlIGNvbnRleHQgaW50ZXJmYWNlIChjb25zdHJ1Y3RlZCBsaXRlcmFsbHkgYnkgbWFueSB0ZXN0IGhhcm5lc3NlcylcbiAqIG5lZWRzIG5vIG5ldyBmaWVsZDsgZW50cmllcyBkcm9wIHdpdGggdGhlIGNvbnRleHQuXG4gKi9cbmNvbnN0IGFjdGl2ZUJhcnJpZXJTYWZldHlOZXRzID0gbmV3IFdlYWtTZXQ8V29ya2Zsb3dPcmNoZXN0cmF0b3JDb250ZXh0PigpO1xuXG4vKipcbiAqIFRoZSBiYXJyaWVyIHJlZ2lzdHJ5J3Mgc2FmZXR5IG5ldDogT05FIGlkbGUtZ2F0ZWQgZGlzcGVuc2VyIHBlciBjb250ZXh0IHRoYXRcbiAqIHJldGlyZXMsIGF0IGVhY2ggb2JzZXJ2YXRpb24gb2YgZGVsaXZlcnkgaWRsZSwgb25seSB0aGUgTE9XRVNULWluZGV4IGVudHJ5XG4gKiBzdGlsbCByZWdpc3RlcmVkLCB0aGVuIHlpZWxkcyBzbyB0aGUgY2hhaW4gaXQgcmVsZWFzZWQgY2FuIHJ1biBiZWZvcmUgdGhlXG4gKiBuZXh0IHJldGlyZW1lbnQgaXMgY29uc2lkZXJlZC5cbiAqXG4gKiBXaHkgb25lIG9yZGVyZWQgZGlzcGVuc2VyIGFuZCBub3QgYSBwb2xsIHBlciBiYXJyaWVyICh3aGljaCBpcyB3aGF0IHRoaXNcbiAqIHJlcGxhY2VkKTogdGhlIG9yZGVyIG9mIHNhZmV0eS1uZXQgcmV0aXJlbWVudHMgZGVjaWRlcyB0aGUgZGVsaXZlcnkgb3JkZXIgb2ZcbiAqIGV2ZXJ5IGNoYWluIHBhcmtlZCBiZWhpbmQgYW4gdW5jbGFpbWVkIGJ1ZmZlcmVkIGhvb2sgcGF5bG9hZCDigJQgYSBob29rIHRoZVxuICogd29ya2Zsb3cgbmV2ZXIgcmVhZHMgKGEgZmlyZS1hbmQtZm9yZ2V0IGBjcmVhdGVIb29rYCkgcGFya3MgZXZlcnkgbGF0ZXJcbiAqIGFybWVkIHdhaXQvaG9vayBiZWhpbmQgYSBiYXJyaWVyIHRoYXQgb25seSB0aGlzIG5ldCBjYW4gcmV0aXJlLiBQZXItYmFycmllclxuICogcG9sbHMgZmlyZSBpbiB3aGF0ZXZlciBvcmRlciB0aGVpciByZS1hcm0gY3ljbGVzIGxhbmQsIGFuZCBlYWNoIHJlLWFybVxuICogYXR0YWNoZXMgdG8gYSBgcHJvbWlzZVF1ZXVlYCB0aGF0IGdyb3dzIGJldHdlZW4gY2hlY2tzLCBzbyB3aXRoIHNldmVyYWxcbiAqIHBhcmtlZCBzZWdtZW50cyB0aGUgcmVsZWFzZSBvcmRlciBkZWNheXMgdG8gdGltaW5nIG5vaXNlLiBEcmF3cyAoYHVzZVN0ZXBgXG4gKiBjb3JyZWxhdGlvbiBpZHMpIHRoZW4gZGVwZW5kIG9uIHdoaWNoIHNlZ21lbnQgaGFwcGVuZWQgdG8gcmVsZWFzZSBmaXJzdCDigJRcbiAqIGNvbmNyZXRlbHksIG9uIGhvdyBNVUNIIGxvZyB0aGUgcmVwbGF5IGxvYWRlZCwgc2luY2UgdGhhdCBkZWNpZGVzIHdoYXQgaXMgaW5cbiAqIHRoZSByZWdpc3RyeS4gVGhhdCBpcyB0aGUgbWVjaGFuaXNtIGJlaGluZCBzbG90LW1vZGUgQ09SUlVQVEVEX0VWRU5UX0xPRyBvblxuICogc3Rvcm0tc2hhcGVkIHJ1bnMgKHNlZSBzdG9ybS1sb2ctcmVwbGF5LnRlc3QudHMsIGJ1aWx0IGZyb20gYSBwcm9kdWN0aW9uXG4gKiBsb2cpOiB0d28gcmVwbGF5cyBvZiB0aGUgc2FtZSBydW4gaG9sZGluZyBkaWZmZXJlbnQtbGVuZ3RoIHByZWZpeGVzIGJvdW5kXG4gKiB0aGUgc2FtZSBjb3JyZWxhdGlvbiBvcmRpbmFsIHRvIGRpZmZlcmVudCBzdGVwcy5cbiAqXG4gKiBSZXRpcmluZyBsb3dlc3QtZmlyc3QgaXMgbm90IG1lcmVseSB0aWR5LCBpdCBpcyB0aGUgb25seSBvcmRlciB0aGF0IGNhbm5vdFxuICogaW52ZXJ0IHRoZSBsb2c6IGV2ZXJ5IGdhdGUgcG9pbnRzIGZyb20gYSBoaWdoZXIgaW5kZXggdG8gYSBzdHJpY3RseSBsb3dlclxuICogb25lLCBzbyBhdCBkZWxpdmVyeSBpZGxlIHRoZSBsb3dlc3QgdW5kZWxpdmVyZWQgZW50cnkgZ2F0ZXMgb24gbm90aGluZ1xuICogc3RpbGwgcmVnaXN0ZXJlZCDigJQgaXQgaXMgdGhlIGhlYWQgb2YgZXZlcnkgcGFya2VkIGNoYWluIChpbiBwcmFjdGljZSwgdGhlXG4gKiB1bmNsYWltZWQgcGF5bG9hZCBpdHNlbGYpLiBSZWxlYXNpbmcgaXQgbGV0cyB0aGUgY2hhaW4gYWJvdmUgZGVsaXZlclxuICogdGhyb3VnaCB0aGUgb3JkaW5hcnkgYmFycmllciBvcmRlcjsgYW55dGhpbmcgdGhlIHJlbGVhc2Ugd2FrZXMgZmxpcHNcbiAqIHtAbGluayBoYXNQYXJrZWRDb21taXR0ZWREZWxpdmVyeX0gYmFjayB0byB0cnVlLCB3aGljaCByZS1ibG9ja3MgdGhpc1xuICogZGlzcGVuc2VyIHVudGlsIHRoZSBjaGFpbiBoYXMgZnVsbHkgZHJhaW5lZC4gQSBoaWdoZXIgZW50cnkgbXVzdCBuZXZlciBiZVxuICogcmV0aXJlZCB3aGlsZSBhIGxvd2VyIG9uZSBpcyByZWdpc3RlcmVkIOKAlCB0aGF0IGlzIGV4YWN0bHkgdGhlIGludmVyc2lvblxuICogZGVzY3JpYmVkIG9uIHtAbGluayBhd2FpdEVhcmxpZXJEZWxpdmVyaWVzfS5cbiAqXG4gKiBUaGUgZGlzcGVuc2VyIGdvZXMgZG9ybWFudCB3aGVuIHRoZSByZWdpc3RyeSBlbXB0aWVzIGFuZCBpcyByZS1hcm1lZCBieSB0aGVcbiAqIG5leHQgcmVnaXN0cmF0aW9uLCBzbyBhbiBpZGxlIGNvbnRleHQgaG9sZHMgbm8gbGl2ZSB0aW1lci5cbiAqL1xuZnVuY3Rpb24gZW5zdXJlQmFycmllclNhZmV0eU5ldChjdHg6IFdvcmtmbG93T3JjaGVzdHJhdG9yQ29udGV4dCk6IHZvaWQge1xuICBjb25zdCBiYXJyaWVycyA9IGN0eC5wZW5kaW5nRGVsaXZlcnlCYXJyaWVycztcbiAgaWYgKCFiYXJyaWVycyB8fCBhY3RpdmVCYXJyaWVyU2FmZXR5TmV0cy5oYXMoY3R4KSkge1xuICAgIHJldHVybjtcbiAgfVxuICBhY3RpdmVCYXJyaWVyU2FmZXR5TmV0cy5hZGQoY3R4KTtcbiAgY29uc3QgcmVhcm0gPSAoKSA9PiB7XG4gICAgc2V0VGltZW91dChjaGVjaywgMCk7XG4gIH07XG4gIC8vIEEgcmVqZWN0ZWQgcHJvbWlzZVF1ZXVlIHNldHRsZXMgaW1tZWRpYXRlbHkgYW5kIGZvcmV2ZXIsIHNvIHJlLWFybWluZ1xuICAvLyB0aHJvdWdoIGl0IGF0IHRoZSBub3JtYWwgY2FkZW5jZSB3b3VsZCBkZWdlbmVyYXRlIGludG8gYSBidXN5IGxvb3Agb24gYW5cbiAgLy8gYWJhbmRvbmVkIGNvbnRleHQuIEJhY2sgb2ZmIGluc3RlYWQ6IGNvcnJlY3RuZXNzIG9ubHkgbmVlZHMgdGhlIGRpc3BlbnNlclxuICAvLyB0byBzdGlsbCBleGlzdCwgc2luY2UgdGhlIHJlZ2lzdHJ5IGdhdGVzIHN1c3BlbnNpb24gdmlhIGlzRGVsaXZlcnlJZGxlXG4gIC8vIGFuZCBhIGRlYWQgZGlzcGVuc2VyIHdvdWxkIHdlZGdlIHRoZSBydW4uXG4gIGNvbnN0IHJlYXJtQWZ0ZXJSZWplY3Rpb24gPSAoKSA9PiB7XG4gICAgc2V0VGltZW91dChjaGVjaywgNTApO1xuICB9O1xuICBjb25zdCBjaGVjayA9ICgpID0+IHtcbiAgICBpZiAoYmFycmllcnMuc2l6ZSA9PT0gMCkge1xuICAgICAgLy8gRG9ybWFudC4gVGhlIG5leHQgcmVnaXN0ZXJEZWxpdmVyeUJhcnJpZXIgcmUtYXJtcy5cbiAgICAgIGFjdGl2ZUJhcnJpZXJTYWZldHlOZXRzLmRlbGV0ZShjdHgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoIWNhblJldGlyZUFiYW5kb25lZEJhcnJpZXJzKGN0eCkpIHtcbiAgICAgIC8vIEEgZGVsaXZlcnkgaXMgaHlkcmF0aW5nIG9yIGNvbW1pdHRlZC1idXQtcGFya2VkIG9uIGl0cyBkZWZlcnJhbDsgbGV0XG4gICAgICAvLyB0aGUgcXVldWUgZHJhaW4gYW5kIHJlLWNoZWNrIGEgdGljayBsYXRlciAoc2FtZSBjYWRlbmNlIGFzXG4gICAgICAvLyBzY2hlZHVsZVdoZW5JZGxlKS5cbiAgICAgIGN0eC5wcm9taXNlUXVldWUudGhlbihyZWFybSwgcmVhcm1BZnRlclJlamVjdGlvbik7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIElkbGUgd2l0aCBlbnRyaWVzIGxlZnQ6IG5vdGhpbmcgcmVtYWluaW5nIGRlbGl2ZXJzIG9uIGl0cyBvd24sIHNvXG4gICAgLy8gcmVsZWFzZSBwYXJrZWQgY2hhaW5zIGZyb20gdGhlIGhlYWQg4oCUIGxvd2VzdCBpbmRleCBmaXJzdCwgb25lIGF0IGFcbiAgICAvLyB0aW1lLCByZS1yZWFkaW5nIGlkbGUgYmV0d2VlbiByZXRpcmVtZW50cy4gQSByZXRpcmVtZW50IHRoYXQgd2FrZXMgYVxuICAgIC8vIGNoYWluIGZsaXBzIHtAbGluayBoYXNQYXJrZWRDb21taXR0ZWREZWxpdmVyeX0gc3luY2hyb25vdXNseSAoaXQgaXNcbiAgICAvLyBjb21wdXRlZCBmcm9tIHRoZSByZWdpc3RyeSB0aGlzIGxvb3AganVzdCBtdXRhdGVkKSwgd2hpY2ggc3RvcHMgdGhlXG4gICAgLy8gc3dlZXAgc28gdGhlIGNoYWluIGRlbGl2ZXJzIGJlZm9yZSBhbnl0aGluZyBhYm92ZSBpdCBpcyByZWxlYXNlZC4gQVxuICAgIC8vIHJldGlyZW1lbnQgdGhhdCB3YWtlcyBub3RoaW5nIChhIHN0YWxlIHBheWxvYWQgbm8gZGVsaXZlcnkgZ2F0ZXMgb24pXG4gICAgLy8ga2VlcHMgdGhlIHN3ZWVwIGdvaW5nLCBzbyBhIGJhY2tsb2cgb2YgdGhvc2UgZHJhaW5zIGluIE9ORSBpZGxlXG4gICAgLy8gb2JzZXJ2YXRpb24g4oCUIHBhY2luZyB0aGVtIG9uZSBwZXIgdGltZXIgdGljayB3b3VsZCBob2xkIGNvbnN1bWVkLWJ1dC1cbiAgICAvLyB1bmRlbGl2ZXJlZCBldmVudHMgaG9zdGFnZSBsb25nIGVub3VnaCB0byB0cmlwIHRoZSBldmVudHMgY29uc3VtZXInc1xuICAgIC8vIHVuY29uc3VtZWQtZXZlbnQgZGVhZGxpbmUgYW5kIGZhaWwgaGVhbHRoeSByZXBsYXlzLlxuICAgIHdoaWxlIChiYXJyaWVycy5zaXplID4gMCAmJiBjYW5SZXRpcmVBYmFuZG9uZWRCYXJyaWVycyhjdHgpKSB7XG4gICAgICBsZXQgbG93ZXN0SW5kZXg6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgICAgIGxldCBsb3dlc3RFbnRyeTogRGVsaXZlcnlCYXJyaWVyRW50cnkgfCB1bmRlZmluZWQ7XG4gICAgICBmb3IgKGNvbnN0IFtpbmRleCwgZW50cnldIG9mIGJhcnJpZXJzKSB7XG4gICAgICAgIGlmIChsb3dlc3RJbmRleCA9PT0gdW5kZWZpbmVkIHx8IGluZGV4IDwgbG93ZXN0SW5kZXgpIHtcbiAgICAgICAgICBsb3dlc3RJbmRleCA9IGluZGV4O1xuICAgICAgICAgIGxvd2VzdEVudHJ5ID0gZW50cnk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGxvd2VzdEVudHJ5Py5yZXRpcmUoKTtcbiAgICB9XG4gICAgc2V0VGltZW91dChjaGVjaywgMCk7XG4gIH07XG4gIHNldFRpbWVvdXQoY2hlY2ssIDApO1xufVxuXG4vKipcbiAqIFdoZXRoZXIgdGhlIHNhZmV0eS1uZXQgZGlzcGVuc2VyIG1heSByZXRpcmUgYWJhbmRvbmVkIGJhcnJpZXJzIHJpZ2h0IG5vdzpcbiAqIG5vIGh5ZHJhdGlvbiBpbiBmbGlnaHQgYW5kIG5vIGNvbW1pdHRlZCBkZWxpdmVyeSBzdGlsbCB3b3JraW5nIHRocm91Z2ggaXRzXG4gKiBkZXRhY2hlZCBkZWZlcnJhbC4gVGhpcyBpcyBkZWxpYmVyYXRlbHkgV0VBS0VSIHRoYW4ge0BsaW5rIGlzRGVsaXZlcnlJZGxlfTpcbiAqIHRoZSBkaXNwZW5zZXIgaXMgd2hhdCBlbXB0aWVzIHRoZSByZWdpc3RyeSwgc28gZ2F0aW5nIGl0IG9uIHJlZ2lzdHJ5XG4gKiBlbXB0aW5lc3Mgd291bGQgZ2F0ZSBpdHMgb3duIHdvcmsuXG4gKi9cbmZ1bmN0aW9uIGNhblJldGlyZUFiYW5kb25lZEJhcnJpZXJzKGN0eDogV29ya2Zsb3dPcmNoZXN0cmF0b3JDb250ZXh0KTogYm9vbGVhbiB7XG4gIHJldHVybiBjdHgucGVuZGluZ0RlbGl2ZXJpZXMgPT09IDAgJiYgIWhhc1BhcmtlZENvbW1pdHRlZERlbGl2ZXJ5KGN0eCk7XG59XG5cbi8qKlxuICogV2hldGhlciBzb21lIHJlZ2lzdGVyZWQgYnJhbmNoLWRlY2lkaW5nIGRlbGl2ZXJ5IGlzIGdvaW5nIHRvIHJlYWNoIHRoZVxuICogd29ya2Zsb3cgd2l0aG91dCBhbnkgZnVydGhlciBoZWxwIChpdCBpcyBhcm1lZCBhbmQgbm90IHRyYW5zaXRpdmVseSBwYXJrZWRcbiAqIGJlaGluZCBhbiB1bmNsYWltZWQgYnVmZmVyZWQgcGF5bG9hZCDigJQgc2VlIHtAbGluayByZXNvbHZlc09uSXRzT3dufSkgYnV0XG4gKiBoYXMgbm90IGJlZW4gaGFuZGVkIG92ZXIgeWV0LlxuICpcbiAqIFRoaXMgaXMgdGhlIGRlbGl2ZXJ5IHN0YXRlIGBwZW5kaW5nRGVsaXZlcmllc2AgY2Fubm90IHNlZS4gVGhhdCBjb3VudGVyXG4gKiBjb3ZlcnMgdGhlIGh5ZHJhdGlvbiB3aW5kb3cgaW5zaWRlIGEgc2VyaWFsIGBwcm9taXNlUXVldWVgIHNsb3QgYW5kIGlzXG4gKiByZWxlYXNlZCB0aGVyZSwgd2hpbGUgdGhlIGRlbGl2ZXJ5J3MgYHJlc29sdmUoKWAgcnVucyBsYXRlciwgZnJvbSBhXG4gKiBkZXRhY2hlZCBjb250aW51YXRpb24gYmVoaW5kIHtAbGluayBhd2FpdEVhcmxpZXJEZWxpdmVyaWVzfSDigJQgaW5jbHVkaW5nIGl0c1xuICogbWFjcm90YXNrIHlpZWxkIHdoZW5ldmVyIHRoZSBkZWxpdmVyeSBoYWQgdG8gZGVmZXIuIFJlcGxheWluZyBhIGJhdGNoIG9mIE5cbiAqIHBhcmFsbGVsIHN0ZXAgcmVzdWx0cyBjb25zdW1lZCBpbiBvbmUgZHJhaW4gd2luZG93IGxlYXZlcyBOLTEgb2YgdGhlbVxuICogcGFya2VkIG9uIHRoYXQgeWllbGQgd2l0aCBgcGVuZGluZ0RlbGl2ZXJpZXNgIGFscmVhZHkgYXQgMC4gQW4gaWRsZSBjaGVja1xuICogYXJtZWQgZHVyaW5nIHRoZSBzYW1lIHdpbmRvdyAoYSBwZW5kaW5nIGBzbGVlcCgpYCBhcm1zIG9uZSBvbiBldmVyeSByZXBsYXkpXG4gKiBjb3VsZCB0aGVuIG9ic2VydmUgXCJpZGxlXCIgbWlkLWRlZmVycmFsIGFuZCByYWlzZSBhIGBXb3JrZmxvd1N1c3BlbnNpb25gXG4gKiBCRUZPUkUgdGhlIHdvcmtmbG93J3Mgb3duIGNvbnRpbnVhdGlvbnMgcmFuIOKAlCBhIHN1c3BlbnNpb24gY2Fycnlpbmcgbm9uZSBvZlxuICogdGhlIGZvbGxvdy11cCB3b3JrIHRoZSBiYXRjaCB3YXMgYWJvdXQgdG8gY3JlYXRlLCB3aGljaCB0aGUgcnVudGltZVxuICogZHV0aWZ1bGx5IHNjaGVkdWxlcyBhcyBub3RoaW5nLCBsZWF2aW5nIHRoZSBydW4gZG9ybWFudCB1bnRpbCBhbiB1bnJlbGF0ZWRcbiAqIHRpbWVyIGZpcmVzICh2ZXJjZWwvd29ya2Zsb3cjMzE4MykuXG4gKlxuICogRGVsaXZlcmllcyB0aGF0IGRvIE5PVCByZXNvbHZlIG9uIHRoZWlyIG93biBtdXN0IGJlIGV4Y2x1ZGVkLCBub3QgZm9yXG4gKiBhY2N1cmFjeSBidXQgZm9yIHRlcm1pbmF0aW9uOiBhbiB1bmNsYWltZWQgYnVmZmVyZWQgaG9vayBwYXlsb2FkIGlzIHJldGlyZWRcbiAqIEJZIHRoZSBpZGxlIHNhZmV0eSBuZXQgaW4ge0BsaW5rIHJlZ2lzdGVyRGVsaXZlcnlCYXJyaWVyfSwgc28gY291bnRpbmcgaXRcbiAqIGhlcmUgd291bGQgZ2F0ZSBpdHMgb3duIHJldGlyZW1lbnQuIFRoYXQgcmVhc29uaW5nIGV4dGVuZHMgdG8gd2hhdGV2ZXIgaXNcbiAqIHBhcmtlZCBiZWhpbmQgc3VjaCBhIHBheWxvYWQg4oCUIGEgd2FpdCwgYW5kIGEgc3RlcCBnYXRpbmcgb24gdGhhdCB3YWl0IOKAlCBmb3JcbiAqIHRoZSBzYW1lIHJlYXNvbjogdGhlIHdob2xlIGNoYWluIG1vdmVzIG9ubHkgb25jZSB0aGUgbmV0IGZpcmVzLCBhbmQgaXRcbiAqIGNhbm5vdCBmaXJlIHdoaWxlIHRoZSBjaGFpbiBpcyBjb3VudGVkLiBTZWxmLXJlc29sdmluZyBkZWxpdmVyaWVzIGFsd2F5c1xuICogZGVsaXZlciBmcm9tIHRoZWlyIG93biBjaGFpbnMgKHNlZSB0aGUgSU5WQVJJQU5UIG9uXG4gKiB7QGxpbmsgcmVnaXN0ZXJEZWxpdmVyeUJhcnJpZXJ9KSBhbmQgbmV2ZXIgbmVlZCB0aGF0IG5ldCwgc28gd2FpdGluZyBvblxuICogdGhlbSBpcyBkZWFkbG9jay1mcmVlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaGFzUGFya2VkQ29tbWl0dGVkRGVsaXZlcnkoXG4gIGN0eDogV29ya2Zsb3dPcmNoZXN0cmF0b3JDb250ZXh0XG4pOiBib29sZWFuIHtcbiAgY29uc3QgYmFycmllcnMgPSBjdHgucGVuZGluZ0RlbGl2ZXJ5QmFycmllcnM7XG4gIGlmICghYmFycmllcnMgfHwgYmFycmllcnMuc2l6ZSA9PT0gMCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICAvLyBTaGFyZWQgYWNyb3NzIHRoaXMgY2FsbCBvbmx5IOKAlCBzZWUgYHJlc29sdmVzT25JdHNPd25gLlxuICBjb25zdCBzZWxmUmVzb2x2aW5nID0gbmV3IE1hcDxudW1iZXIsIGJvb2xlYW4+KCk7XG4gIGZvciAoY29uc3QgW2luZGV4LCBlbnRyeV0gb2YgYmFycmllcnMpIHtcbiAgICBpZiAocmVzb2x2ZXNPbkl0c093bihiYXJyaWVycywgaW5kZXgsIGVudHJ5LCBzZWxmUmVzb2x2aW5nKSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuLyoqXG4gKiBXaGV0aGVyIG5vIGRhdGEgZGVsaXZlcnkgKHN0ZXAgcmVzdWx0LCBob29rIHBheWxvYWQpIGlzIGluIGZsaWdodCByaWdodCBub3cuXG4gKlxuICogXCJJbiBmbGlnaHRcIiBpcyB0d28gZGlzdGluY3Qgd2luZG93cywgZWFjaCB3aXRoIGl0cyBvd24gZ3VhcmQ6XG4gKiBgcGVuZGluZ0RlbGl2ZXJpZXMgPiAwYCBjb3ZlcnMgaHlkcmF0aW9uIGluc2lkZSB0aGUgc2VyaWFsIHF1ZXVlIHNsb3RzLCBhbmRcbiAqIHtAbGluayBoYXNQYXJrZWRDb21taXR0ZWREZWxpdmVyeX0gY292ZXJzIHRoZSBkZXRhY2hlZCBnYXAgYmV0d2VlbiBhIHNsb3RcbiAqIHJlbGVhc2luZyB0aGF0IGNvdW50ZXIgYW5kIHRoZSBkZWxpdmVyeSdzIGByZXNvbHZlKClgIGFjdHVhbGx5IHJ1bm5pbmcg4oCUXG4gKiBkZWxpYmVyYXRlbHkgb3V0c2lkZSBgcGVuZGluZ0RlbGl2ZXJpZXNgIChzZWUgc3RlcC50cyksIGFuZCBpbnZpc2libGUgdG8gaXQuXG4gKlxuICogQW55dGhpbmcgdGhhdCBkZWNpZGVzIGEgcmVwbGF5IGlzIG92ZXIsIG9yIHRoYXQgYSByZXBsYXkgd2VudCB3cm9uZywgaGFzIHRvXG4gKiBjb25zdWx0IHRoaXMgZmlyc3Q6IHdoaWxlIGl0IGlzIGZhbHNlIHRoZSB3b3JrZmxvdyBWTSBpcyBtaWQtcmVhY3Rpb24sIHNvXG4gKiB3aGF0IGl0IGhhcyBhbmQgaGFzIG5vdCBkb25lIHlldCBzYXlzIG5vdGhpbmcgYWJvdXQgdGhlIHJ1bi4gVHdvIGNhbGxlcnNcbiAqIHJlYWQgaXQsIGZvciB0aGUgdHdvIHN1Y2ggZGVjaXNpb25zOiB7QGxpbmsgc2NoZWR1bGVXaGVuSWRsZX0gZm9yIHRoZVxuICogc3VzcGVuc2lvbiwgYW5kIHRoZSBldmVudHMgY29uc3VtZXIncyB1bmNvbnN1bWVkLWV2ZW50IGNoZWNrIGZvciBkaXZlcmdlbmNlLlxuICpcbiAqIEEgbm9uLWVtcHR5IGJhcnJpZXIgcmVnaXN0cnkgY291bnRzIGFzIGluIGZsaWdodCwgZXZlbiB3aGVuIGV2ZXJ5IHJlbWFpbmluZ1xuICogZW50cnkgaXMgcGFya2VkIGJlaGluZCBhbiB1bmNsYWltZWQgYnVmZmVyZWQgcGF5bG9hZC4gVGhvc2UgZW50cmllcyBvbmx5XG4gKiBtb3ZlIHdoZW4gdGhlIHNhZmV0eS1uZXQgZGlzcGVuc2VyIHJldGlyZXMgdGhlbSAobG93ZXN0LWZpcnN0LCBzZWVcbiAqIHtAbGluayBlbnN1cmVCYXJyaWVyU2FmZXR5TmV0fSksIGFuZCB0aGUgZGVsaXZlcmllcyB0aGV5IHJlbGVhc2UgYXJlIHJlYWxcbiAqIHdvcmtmbG93IHJlYWN0aW9ucyDigJQgYSBzdXNwZW5zaW9uIHJhaXNlZCBiZWZvcmUgdGhleSBydW4gd291bGQgYmUgY29tcHV0ZWRcbiAqIGZyb20gYSBWTSB0aGF0IGhhcyBub3Qgc2VlbiB0aGVtLCBzY2hlZHVsaW5nIG5vbmUgb2YgdGhlaXIgZm9sbG93LXVwIHdvcmtcbiAqIGFuZCBsZWF2aW5nIHRoZSBydW4gZG9ybWFudCAodGhlIHZlcmNlbC93b3JrZmxvdyMzMTgzIHNoYXBlKS4gVGhlIGRpc3BlbnNlclxuICogaXRzZWxmIGlzIGdhdGVkIG9uIHtAbGluayBjYW5SZXRpcmVBYmFuZG9uZWRCYXJyaWVyc30sIHRoZSB3ZWFrZXIgcHJlZGljYXRlXG4gKiB3aXRob3V0IHRoZSByZWdpc3RyeSB0ZXJtLCBwcmVjaXNlbHkgc28gaXQgY2FuIGRvIHRoZSBkcmFpbmluZyB0aGF0IHRoaXNcbiAqIHByZWRpY2F0ZSB3YWl0cyBmb3I7IHJlZ2lzdHJ5IHNpemUgc3RyaWN0bHkgZGVjcmVhc2VzIGF0IGVhY2ggcmV0aXJlbWVudCxcbiAqIHNvIGlkbGUgaXMgYWx3YXlzIHJlYWNoZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0RlbGl2ZXJ5SWRsZShjdHg6IFdvcmtmbG93T3JjaGVzdHJhdG9yQ29udGV4dCk6IGJvb2xlYW4ge1xuICByZXR1cm4gKFxuICAgIGN0eC5wZW5kaW5nRGVsaXZlcmllcyA9PT0gMCAmJlxuICAgICghY3R4LnBlbmRpbmdEZWxpdmVyeUJhcnJpZXJzIHx8IGN0eC5wZW5kaW5nRGVsaXZlcnlCYXJyaWVycy5zaXplID09PSAwKVxuICApO1xufVxuXG4vKipcbiAqIFNjaGVkdWxlIGEgY2FsbGJhY2sgdG8gZmlyZSBvbmx5IGFmdGVyIGFsbCBwZW5kaW5nIGRhdGEgZGVsaXZlcmllc1xuICogKHN0ZXAgcmVzdWx0cywgaG9vayBwYXlsb2FkcykgYW5kIGFzeW5jIGRlc2VyaWFsaXphdGlvbiBoYXZlIGNvbXBsZXRlZC5cbiAqIFVzZXMgYSBwb2xsaW5nIGxvb3A6IHNldFRpbWVvdXQoMCkg4oaSIGNoZWNrIHBlbmRpbmdEZWxpdmVyaWVzIGFuZCB0aGVcbiAqIGJhcnJpZXIgcmVnaXN0cnkg4oaSIGlmIGFueXRoaW5nIGlzIHN0aWxsIGluIGZsaWdodCwgd2FpdCBmb3IgcHJvbWlzZVF1ZXVlIOKGklxuICogcmVwZWF0LiBUaGlzIGhhbmRsZXMgdGhlIG11bHRpLXJvdW5kIGRlbGl2ZXJ5IHBhdHRlcm4gd2hlcmUgZWFjaCBob29rXG4gKiBwYXlsb2FkIGRlbGl2ZXJ5IGN5Y2xlIGFwcGVuZHMgbmV3IGFzeW5jIHdvcmsgdG8gdGhlIHByb21pc2VRdWV1ZS4gV2hhdFxuICogY291bnRzIGFzIGluIGZsaWdodCBpcyB7QGxpbmsgaXNEZWxpdmVyeUlkbGV9LlxuICpcbiAqIFRoZSBpbml0aWFsIGBzZXRUaW1lb3V0KDApYCBtYWNyb3Rhc2sgaXMgbG9hZC1iZWFyaW5nIGFuZCBtdXN0IE5PVCBiZVxuICogZG93bmdyYWRlZCB0byBhIG1pY3JvdGFzayAoYHF1ZXVlTWljcm90YXNrYC9gUHJvbWlzZS5yZXNvbHZlKCkudGhlbmApLlxuICogYHBlbmRpbmdEZWxpdmVyaWVzYCBvbmx5IGd1YXJkcyB0aGUgaG9zdC1zaWRlIGh5ZHJhdGlvbiB3aW5kb3c7IGJldHdlZW4gYVxuICogZGVsaXZlcnkncyBgcmVzb2x2ZSgpYCBhbmQgdGhlIHdvcmtmbG93IFZNIGJvZHkgcnVubmluZyBpdHMgY29udGludWF0aW9uIHRvXG4gKiByZWdpc3RlciB0aGUgbmV4dCBzdWJzY3JpYmVyLCBgcGVuZGluZ0RlbGl2ZXJpZXNgIGlzIGFscmVhZHkgMCBldmVuIHRob3VnaFxuICogdGhlIFZNIGlzIG1pZC1yZWFjdGlvbi4gTm9kZSBkb2VzIG5vdCBndWFyYW50ZWUgYSBtaWNyb3Rhc2sgc2NoZWR1bGVkIGluXG4gKiB0aGUgaG9zdCBjb250ZXh0IHNldHRsZXMgYWZ0ZXIgdGhlIGNyb3NzLVZNIHByb21pc2UgY2hhaW4gKHJlc29sdmUgaW4gaG9zdFxuICog4oaSIHdvcmtmbG93IGNvZGUgaW4gVk0g4oaSIHN1YnNjcmliZSBiYWNrIGluIGhvc3QpOyB0aGUgbWFjcm90YXNrIGJvdW5kYXJ5XG4gKiBnaXZlcyB0aGF0IGNoYWluIHRpbWUgdG8gcnVuLCBzbyB0aGUgc3VzcGVuc2lvbiBkb2VzIG5vdCBwcmVlbXB0IGEgc2libGluZ1xuICogZGVsaXZlcnkgc3RpbGwgaW4gZmxpZ2h0LiBFbXBpcmljYWxseSwgcmVwbGFjaW5nIGl0IHdpdGggYHF1ZXVlTWljcm90YXNrYFxuICogYnJlYWtzIGhvb2svc2xlZXAgYFByb21pc2UucmFjZWAgb3JkZXJpbmcgKENvcnJ1cHRlZEV2ZW50TG9nRXJyb3IpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc2NoZWR1bGVXaGVuSWRsZShcbiAgY3R4OiBXb3JrZmxvd09yY2hlc3RyYXRvckNvbnRleHQsXG4gIGZuOiAoKSA9PiB2b2lkXG4pOiB2b2lkIHtcbiAgY29uc3QgY2hlY2sgPSAoKSA9PiB7XG4gICAgaWYgKCFpc0RlbGl2ZXJ5SWRsZShjdHgpKSB7XG4gICAgICAvLyBBIGRlbGl2ZXJ5IGlzIHN0aWxsIGh5ZHJhdGluZywgb3IgaXMgY29tbWl0dGVkIGJ1dCBwYXJrZWQgYmVoaW5kIGl0c1xuICAgICAgLy8gZGVmZXJyYWwgKHdob3NlIHJlc29sdmUgcnVucyBvbiBhIGRldGFjaGVkIHRpbWVyLCBub3QgdGhpcyBxdWV1ZSkuXG4gICAgICAvLyBFaXRoZXIgd2F5OiBsZXQgdGhlIHF1ZXVlIGRyYWluLCB0aGVuIHJlLWNoZWNrIGEgdGltZXIgdGljayBsYXRlci5cbiAgICAgIGN0eC5wcm9taXNlUXVldWUudGhlbigoKSA9PiB7XG4gICAgICAgIHNldFRpbWVvdXQoY2hlY2ssIDApO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGZuKCk7XG4gICAgfVxuICB9O1xuICBzZXRUaW1lb3V0KGNoZWNrLCAwKTtcbn1cbiJdfQ==
|
|
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==
|