@workflow/core 5.0.0-beta.43 → 5.0.0-beta.46
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/attribute-changes.d.ts +3 -5
- package/dist/attribute-changes.d.ts.map +1 -1
- package/dist/attribute-changes.js +2 -2
- package/dist/capabilities.d.ts +6 -6
- package/dist/capabilities.js +8 -8
- 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 +20 -8
- package/dist/events-consumer.d.ts.map +1 -1
- package/dist/events-consumer.js +34 -12
- package/dist/flushable-stream.d.ts +4 -4
- package/dist/flushable-stream.js +13 -13
- package/dist/global.d.ts +4 -2
- package/dist/global.d.ts.map +1 -1
- package/dist/global.js +8 -5
- 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 +29 -71
- package/dist/private.d.ts.map +1 -1
- package/dist/private.js +170 -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 +21 -21
- 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 +206 -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 +132 -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 +27 -12
- package/dist/runtime/resume-hook.d.ts.map +1 -1
- package/dist/runtime/resume-hook.js +200 -200
- package/dist/runtime/resume-latency.d.ts +40 -30
- package/dist/runtime/resume-latency.d.ts.map +1 -1
- package/dist/runtime/resume-latency.js +7 -5
- 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 +22 -5
- package/dist/runtime/run.d.ts.map +1 -1
- package/dist/runtime/run.js +106 -11
- 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 +29 -25
- 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 +42 -25
- package/dist/runtime/step-latency.d.ts.map +1 -1
- package/dist/runtime/step-latency.js +29 -23
- 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 +38 -24
- package/dist/runtime/suspension-handler.d.ts.map +1 -1
- package/dist/runtime/suspension-handler.js +238 -103
- 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 +427 -266
- 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 +23 -22
- package/dist/serialization/hardened.d.ts.map +1 -1
- package/dist/serialization/hardened.js +47 -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 +30 -24
- package/dist/serialization.d.ts +15 -16
- package/dist/serialization.d.ts.map +1 -1
- package/dist/serialization.js +116 -109
- 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.d.ts.map +1 -1
- package/dist/step.js +14 -22
- package/dist/symbols.d.ts +2 -2
- package/dist/symbols.js +3 -3
- package/dist/telemetry/semantic-conventions.d.ts +34 -17
- package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
- package/dist/telemetry/semantic-conventions.js +32 -17
- 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/attribute-dispatcher.d.ts.map +1 -1
- package/dist/workflow/attribute-dispatcher.js +3 -6
- package/dist/workflow/create-hook.js +2 -2
- package/dist/workflow/get-workflow-metadata.js +2 -2
- package/dist/workflow/hook.d.ts.map +1 -1
- package/dist/workflow/hook.js +21 -30
- 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 +26 -13
- 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
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Utils used by the bundler when transforming code
|
|
3
3
|
*/
|
|
4
4
|
import { withResolvers } from '@workflow/utils';
|
|
5
|
+
import { WorkflowSuspension } from './global.js';
|
|
5
6
|
const RegisteredStepsKey = Symbol.for('@workflow/core//registeredSteps');
|
|
6
7
|
const globalSymbols = globalThis;
|
|
7
8
|
// biome-ignore lint/suspicious/noAssignInExpressions: /
|
|
@@ -91,20 +92,20 @@ export function getStepFunction(stepId) {
|
|
|
91
92
|
* blocks on a peer it does not need to:
|
|
92
93
|
*
|
|
93
94
|
* - 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;
|
|
95
|
+
* - a wait defers behind earlier HOOKS and STEPS (not earlier waits, since a
|
|
96
|
+
* wait never needs to queue behind another wait);
|
|
96
97
|
* - a step defers behind earlier WAITS, HOOKS and STEPS.
|
|
97
98
|
*
|
|
98
99
|
* The step-behind-step edge is not redundant with the serial `promiseQueue`.
|
|
99
100
|
* The queue fixes the order in which step results are HYDRATED, but a step no
|
|
100
|
-
* longer resolves inside its queue slot
|
|
101
|
+
* longer resolves inside its queue slot: it captures the outcome there and
|
|
101
102
|
* resolves from a detached continuation once its barrier clears. Two steps
|
|
102
103
|
* agree on that continuation's ordering only while they defer behind the same
|
|
103
104
|
* set, which holds when they are consumed in the same drain window but not
|
|
104
105
|
* across windows: a step consumed later can miss a wait/hook barrier that an
|
|
105
106
|
* earlier step is still parked on, because the barrier retired in between. The
|
|
106
107
|
* earlier step is then waiting out the macrotask yield below while the later
|
|
107
|
-
* one resolves on microtasks, and overtakes it
|
|
108
|
+
* one resolves on microtasks, and overtakes it. See
|
|
108
109
|
* `delivery-barrier-coverage.test.ts`. Deferring behind earlier steps
|
|
109
110
|
* closes that window structurally: the earlier step's barrier is still
|
|
110
111
|
* registered precisely because it has not delivered yet.
|
|
@@ -127,19 +128,24 @@ const DEFER_BEHIND = {
|
|
|
127
128
|
* Those two MUST agree exactly, and the doc block on
|
|
128
129
|
* {@link awaitEarlierDeliveries} stakes deadlock-freedom on it, so the
|
|
129
130
|
* condition lives here rather than being spelled out twice.
|
|
131
|
+
*
|
|
132
|
+
* One deliberate exception: the log-order-draws turnstile in
|
|
133
|
+
* {@link quiesceEarlierCascades} waits on ANY lower armed entry, a strictly
|
|
134
|
+
* wider relation than this one. Why that width cannot deadlock the
|
|
135
|
+
* safety-net dispenser is argued at the turnstile itself.
|
|
130
136
|
*/
|
|
131
137
|
function gatesOn(kind, index, otherIndex, other) {
|
|
132
138
|
if (otherIndex >= index || !DEFER_BEHIND[kind].includes(other.kind)) {
|
|
133
139
|
return false;
|
|
134
140
|
}
|
|
135
141
|
// A step skips an UNARMED earlier entry (an unclaimed buffered hook
|
|
136
|
-
// payload)
|
|
142
|
+
// payload). See the asymmetry described on `awaitEarlierDeliveries`. The
|
|
137
143
|
// skip is direct, never transitive: armed entries are still gated on, even
|
|
138
144
|
// when they are themselves parked behind such a payload.
|
|
139
145
|
return !(kind === 'step' && !other.armed);
|
|
140
146
|
}
|
|
141
147
|
/**
|
|
142
|
-
* Whether `entry` will resolve on its own
|
|
148
|
+
* Whether `entry` will resolve on its own: it is armed, and every earlier
|
|
143
149
|
* delivery it actually gates on ({@link gatesOn}) will likewise resolve on its
|
|
144
150
|
* own.
|
|
145
151
|
*
|
|
@@ -155,7 +161,7 @@ function gatesOn(kind, index, otherIndex, other) {
|
|
|
155
161
|
*
|
|
156
162
|
* Recursion terminates because every edge points to a strictly smaller index.
|
|
157
163
|
* `memo` keeps the walk linear in registry size, and the registry is not small
|
|
158
|
-
* by construction
|
|
164
|
+
* by construction: `EventsConsumer` drains consecutively consumable events
|
|
159
165
|
* synchronously while barriers only retire on microtask-driven deliveries, so
|
|
160
166
|
* a fan-out of `Promise.race([hook, sleep])` branches accumulates one barrier
|
|
161
167
|
* per branch per kind. The memo MUST be per-call: `armed` mutates between
|
|
@@ -163,7 +169,7 @@ function gatesOn(kind, index, otherIndex, other) {
|
|
|
163
169
|
*
|
|
164
170
|
* The memo is an optimization, not a correctness requirement. It once was one:
|
|
165
171
|
* `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)
|
|
172
|
+
* step delivery, with no early exit, which unmemoized is T(n) = Σ T(j),
|
|
167
173
|
* measured at 4.3e8 recursive calls (84s) for 40 alternating armed hook/wait
|
|
168
174
|
* barriers. That call site is gone; a step now tests `armed` directly. The one
|
|
169
175
|
* surviving caller, {@link hasParkedCommittedDelivery}, cannot reach that
|
|
@@ -203,8 +209,8 @@ function computeResolvesOnItsOwn(barriers, index, entry, memo) {
|
|
|
203
209
|
* earlier in the log than `eventIndex` and that a delivery of `kind` defers
|
|
204
210
|
* behind (see {@link DEFER_BEHIND}), so that this resolution is handed to the
|
|
205
211
|
* workflow only after all relevant earlier-in-log deliveries have been. This
|
|
206
|
-
* is what keeps a `Promise.race`
|
|
207
|
-
* a concurrent branch
|
|
212
|
+
* is what keeps a `Promise.race` (or the ULID a follow-up `useStep` draws on
|
|
213
|
+
* a concurrent branch) deterministic and aligned with the committed event
|
|
208
214
|
* log, independent of microtask-hop counts, hydration time, or race-argument
|
|
209
215
|
* order. When this delivery does have to wait, it also yields a macrotask
|
|
210
216
|
* afterwards so the earlier delivery's consumer can run to its own next
|
|
@@ -217,10 +223,10 @@ function computeResolvesOnItsOwn(barriers, index, entry, memo) {
|
|
|
217
223
|
* One asymmetry: a STEP result skips any earlier delivery that is UNARMED,
|
|
218
224
|
* i.e. a buffered hook payload no consumer has claimed. Such a payload is
|
|
219
225
|
* delivered only when the workflow next reads the hook, and reaching that read
|
|
220
|
-
*
|
|
226
|
+
* often requires the step result itself (`await stepX()` before the
|
|
221
227
|
* read). Gating the step on it would stall the workflow until the barrier's
|
|
222
228
|
* idle safety net fires, which then releases every delivery queued behind that
|
|
223
|
-
* payload at once
|
|
229
|
+
* payload at once, losing exactly the race this ordering exists to protect.
|
|
224
230
|
* Waits and hooks keep gating on unclaimed payloads: for them, waiting for the
|
|
225
231
|
* claim IS the ordering guarantee (a `wait_completed` must not preempt a
|
|
226
232
|
* payload the log ordered first).
|
|
@@ -231,7 +237,7 @@ function computeResolvesOnItsOwn(barriers, index, entry, memo) {
|
|
|
231
237
|
* there is: a workflow that creates a hook it does not read on this branch,
|
|
232
238
|
* races `step` against `sleep`, and has the log say the sleep won. The step
|
|
233
239
|
* would then overtake the wait, both branches would swap the correlation ids
|
|
234
|
-
* they draw next, and replay would diverge
|
|
240
|
+
* they draw next, and replay would diverge. See
|
|
235
241
|
* `step-delivery-ordering.test.ts`. Waiting instead is safe because the
|
|
236
242
|
* payload's own idle safety net retires it and the whole chain then delivers
|
|
237
243
|
* in log order; {@link hasParkedCommittedDelivery} deliberately reports such a
|
|
@@ -242,19 +248,120 @@ function computeResolvesOnItsOwn(barriers, index, entry, memo) {
|
|
|
242
248
|
* structural: safety-net retirements go through one per-context dispenser that
|
|
243
249
|
* only ever retires the lowest-index entry at delivery idle, and every
|
|
244
250
|
* retirement that wakes a chain flips {@link hasParkedCommittedDelivery} back
|
|
245
|
-
* to true, re-blocking the dispenser until the chain has drained
|
|
251
|
+
* to true, re-blocking the dispenser until the chain has drained. See
|
|
246
252
|
* {@link ensureBarrierSafetyNet}. (This used to rest on the FIFO of one idle
|
|
247
253
|
* poll per barrier, which held for a single parked segment but decayed to
|
|
248
|
-
* timing noise with several
|
|
254
|
+
* timing noise with several: the release order, and therefore the ULIDs
|
|
249
255
|
* drawn by the woken branches, then depended on how much log the replay had
|
|
250
256
|
* loaded. storm-log-replay.test.ts replays a production log corrupted exactly
|
|
251
257
|
* that way.)
|
|
252
258
|
*/
|
|
259
|
+
/**
|
|
260
|
+
* Whether correlation-id draw order is pinned to event-log order. Default ON:
|
|
261
|
+
* only the literal string `WORKFLOW_LOG_ORDER_DRAWS=0` opts out. `=false`,
|
|
262
|
+
* `=off`, and every other value keep it enabled. Read per call so tests can
|
|
263
|
+
* flip it.
|
|
264
|
+
*
|
|
265
|
+
* Off, a delivery that had to defer yields ONE macrotask after its
|
|
266
|
+
* predecessors resolve. This is enough for short consumers, but a woken branch
|
|
267
|
+
* whose path to its next draw crosses more hops (a `Promise.race` resolution, a
|
|
268
|
+
* user-level semaphore, an async-iterator read) can still be overtaken by a
|
|
269
|
+
* later-in-log delivery's shorter cascade, so the run's draw order, including
|
|
270
|
+
* its correlation ids, depends on how much log this replay loaded.
|
|
271
|
+
* On, the yield becomes a fixpoint: the delivery resolves only once every
|
|
272
|
+
* earlier cascade has quiesced, making the draw sequence a pure function of
|
|
273
|
+
* the dense log, stable under prefix extension, and concurrent writers'
|
|
274
|
+
* duplicate creates identical (deduped) instead of colliding.
|
|
275
|
+
*/
|
|
276
|
+
function isLogOrderDrawsEnabled() {
|
|
277
|
+
return process.env.WORKFLOW_LOG_ORDER_DRAWS !== '0';
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* One quiescence turn: lets the entire pending microtask queue drain, then
|
|
281
|
+
* yields to the event loop once. `setImmediate` (check phase) is used where
|
|
282
|
+
* available because Node clamps `setTimeout(0)` to ~1ms while `setImmediate`
|
|
283
|
+
* costs ~20µs. Every branch-deciding delivery pays this turn at least
|
|
284
|
+
* once, so on a sequential replay the clamp is the whole cost. Timers still
|
|
285
|
+
* run between consecutive turns (the loop re-enters the event loop each
|
|
286
|
+
* iteration, passing through the timers phase), so chains parked on the
|
|
287
|
+
* safety-net dispenser's `setTimeout` cadence are not starved.
|
|
288
|
+
*/
|
|
289
|
+
function quiescenceTurn(delayMs) {
|
|
290
|
+
if (delayMs === 0 && typeof setImmediate === 'function') {
|
|
291
|
+
return new Promise((resolve) => setImmediate(resolve));
|
|
292
|
+
}
|
|
293
|
+
return new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Waits until the workflow can make no further progress without another
|
|
297
|
+
* delivery: repeated (promise-queue drain + event-loop turn)s until a full
|
|
298
|
+
* turn passes with no new ULID draws and no hydration in flight.
|
|
299
|
+
*
|
|
300
|
+
* Termination: each extra iteration requires a new ULID draw or a hydration
|
|
301
|
+
* started in the previous turn. `mintCount` counts EVERY draw from the run's
|
|
302
|
+
* sequence, including correlation ids and serialization-driven draws (stream
|
|
303
|
+
* ids minted through the `STABLE_ULID` global while dehydrating). This is
|
|
304
|
+
* conservative in the safe direction: serialization draws only extend the
|
|
305
|
+
* wait, and both body progress and the serialization work one cascade can
|
|
306
|
+
* schedule are finite between deliveries, so the fixpoint is reached. The
|
|
307
|
+
* loop holds this delivery's own barrier registered (its `markDelivered` has
|
|
308
|
+
* not run), so `isDeliveryIdle` stays false and no suspension can preempt the
|
|
309
|
+
* cascade being waited out.
|
|
310
|
+
*
|
|
311
|
+
* A rejected `promiseQueue` settles immediately and forever, so looping at
|
|
312
|
+
* the normal cadence on a failed run would degenerate into a busy loop (the
|
|
313
|
+
* same hazard {@link ensureBarrierSafetyNet} documents). Iterations that
|
|
314
|
+
* observe the queue rejected back off to a 50ms tick instead.
|
|
315
|
+
*/
|
|
316
|
+
async function quiesceEarlierCascades(ctx, eventIndex) {
|
|
317
|
+
for (;;) {
|
|
318
|
+
const mintsBefore = ctx.mintCount ?? 0;
|
|
319
|
+
const pendingBefore = ctx.pendingDeliveries;
|
|
320
|
+
// Settled or rejected, the queue snapshot only orders us behind work
|
|
321
|
+
// already chained; a rejection is the run failing elsewhere.
|
|
322
|
+
const queueRejected = await ctx.promiseQueue.then(() => false, () => true);
|
|
323
|
+
await quiescenceTurn(queueRejected ? 50 : 0);
|
|
324
|
+
if ((ctx.mintCount ?? 0) !== mintsBefore ||
|
|
325
|
+
pendingBefore !== 0 ||
|
|
326
|
+
ctx.pendingDeliveries !== 0) {
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
// Quiet is not enough on its own: several delivery chains can be sitting
|
|
330
|
+
// in this loop at once, and letting the first quiet observation resolve
|
|
331
|
+
// would break the tie by timer arrival. This mode removes that arrival-order
|
|
332
|
+
// dependence. A lower-index ARMED barrier is a delivery committed to
|
|
333
|
+
// happening that has not happened yet, so this one keeps waiting. Unarmed
|
|
334
|
+
// entries (buffered payloads nobody has claimed) do not block, exactly as
|
|
335
|
+
// in `gatesOn`: their handover is claim-driven, which is body-position
|
|
336
|
+
// determined and therefore already a function of the prefix.
|
|
337
|
+
//
|
|
338
|
+
// This is deliberately a WIDER waits-for relation than `gatesOn` (which,
|
|
339
|
+
// e.g., excludes wait→wait): under log-order draws EVERY branch-deciding
|
|
340
|
+
// delivery must resolve in log order, kinds included. The width is safe
|
|
341
|
+
// against the dispenser deadlock that `resolvesOnItsOwn` guards, because
|
|
342
|
+
// the one edge the wider relation adds (waiting on an armed entry that
|
|
343
|
+
// gatesOn does not model) always bottoms out at the same unarmed payload:
|
|
344
|
+
// a lower armed WAIT is non-self-resolving only when it is (transitively)
|
|
345
|
+
// parked behind an unclaimed buffered payload, and a wait gates on every
|
|
346
|
+
// lower hook and step directly, so the spinner here also gates on that
|
|
347
|
+
// payload through `gatesOn` and is itself reported non-self-resolving.
|
|
348
|
+
// The dispenser therefore stays unblocked and retires the chain head; see
|
|
349
|
+
// the parked-chain test in delivery-barrier-coverage.test.ts.
|
|
350
|
+
let lowerArmed = false;
|
|
351
|
+
for (const [index, entry] of ctx.pendingDeliveryBarriers ?? []) {
|
|
352
|
+
if (index < eventIndex && entry.armed) {
|
|
353
|
+
lowerArmed = true;
|
|
354
|
+
break;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
if (!lowerArmed) {
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
253
362
|
export async function awaitEarlierDeliveries(ctx, eventIndex, kind) {
|
|
254
363
|
// Defensive: tolerate contexts that predate this field (test harnesses).
|
|
255
|
-
if (eventIndex === undefined ||
|
|
256
|
-
!ctx.pendingDeliveryBarriers ||
|
|
257
|
-
ctx.pendingDeliveryBarriers.size === 0) {
|
|
364
|
+
if (eventIndex === undefined || !ctx.pendingDeliveryBarriers) {
|
|
258
365
|
return;
|
|
259
366
|
}
|
|
260
367
|
const barriers = ctx.pendingDeliveryBarriers;
|
|
@@ -267,9 +374,22 @@ export async function awaitEarlierDeliveries(ctx, eventIndex, kind) {
|
|
|
267
374
|
}
|
|
268
375
|
if (earlier.length > 0) {
|
|
269
376
|
await Promise.all(earlier);
|
|
377
|
+
}
|
|
378
|
+
if (isLogOrderDrawsEnabled()) {
|
|
379
|
+
// Unconditional, not just when a barrier was still registered: an earlier
|
|
380
|
+
// delivery's barrier deregisters when its resolve() runs, but the branch
|
|
381
|
+
// it woke may still be hops away from its next draw. A later delivery
|
|
382
|
+
// consumed after that deregistration sees an empty gate set, and without
|
|
383
|
+
// this it would resolve mid-cascade and overtake the draw. This is the exact
|
|
384
|
+
// arrival-order dependence this mode exists to remove. Costs one quiet
|
|
385
|
+
// macrotask turn when nothing is in flight.
|
|
386
|
+
await quiesceEarlierCascades(ctx, eventIndex);
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
if (earlier.length > 0) {
|
|
270
390
|
// An earlier delivery being "delivered" only means its `resolve()` ran.
|
|
271
391
|
// 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
|
|
392
|
+
// hops before it reaches its next `useStep` call and draws a ULID: a
|
|
273
393
|
// `for await` over a hook, for instance, resumes the generator, settles
|
|
274
394
|
// the promise from `next()`, and only then runs the loop body. Resolving
|
|
275
395
|
// this delivery on a microtask would let it overtake that branch and
|
|
@@ -297,12 +417,12 @@ export async function awaitEarlierDeliveries(ctx, eventIndex, kind) {
|
|
|
297
417
|
* suspending and never observes it), the barrier auto-resolves at idle.
|
|
298
418
|
*
|
|
299
419
|
* INVARIANT required of every call site: a barrier that is ever `armed` must
|
|
300
|
-
* be paired with a delivery chain that runs unconditionally
|
|
420
|
+
* be paired with a delivery chain that runs unconditionally, attached when
|
|
301
421
|
* the event is consumed (waits, step results, waiting-consumer hook payloads,
|
|
302
422
|
* aborts), or by the `claim()` whose invocation is what arms it (buffered
|
|
303
423
|
* hook payloads). The idle check ({@link scheduleWhenIdle}) refuses to
|
|
304
424
|
* observe idle while an armed, self-resolving barrier is undelivered, and the
|
|
305
|
-
* safety net below is itself idle-gated
|
|
425
|
+
* safety net below is itself idle-gated, so an armed barrier with no
|
|
306
426
|
* unconditional chain would livelock every idle check in the run, including
|
|
307
427
|
* its own retirement.
|
|
308
428
|
*/
|
|
@@ -336,7 +456,7 @@ export function registerDeliveryBarrier(ctx, eventIndex, kind, options = {}) {
|
|
|
336
456
|
// it is retired at idle so a later delivery gated on it cannot deadlock and
|
|
337
457
|
// the registry cannot leak an entry per abandoned delivery. Retirement goes
|
|
338
458
|
// through the context's single ordered dispenser rather than a per-barrier
|
|
339
|
-
// idle poll
|
|
459
|
+
// idle poll. See {@link ensureBarrierSafetyNet} for why the ORDER of these
|
|
340
460
|
// retirements is load-bearing.
|
|
341
461
|
ensureBarrierSafetyNet(ctx);
|
|
342
462
|
return {
|
|
@@ -351,6 +471,9 @@ export function registerDeliveryBarrier(ctx, eventIndex, kind, options = {}) {
|
|
|
351
471
|
* so the context interface (constructed literally by many test harnesses)
|
|
352
472
|
* needs no new field; entries drop with the context.
|
|
353
473
|
*/
|
|
474
|
+
// per-copy-ok: keyed on the orchestrator context object, and a context is armed
|
|
475
|
+
// and observed by the same copy that created it. Entries can never be looked up
|
|
476
|
+
// from another copy because that copy has no reference to the key.
|
|
354
477
|
const activeBarrierSafetyNets = new WeakSet();
|
|
355
478
|
/**
|
|
356
479
|
* The barrier registry's safety net: ONE idle-gated dispenser per context that
|
|
@@ -360,13 +483,13 @@ const activeBarrierSafetyNets = new WeakSet();
|
|
|
360
483
|
*
|
|
361
484
|
* Why one ordered dispenser and not a poll per barrier (which is what this
|
|
362
485
|
* replaced): the order of safety-net retirements decides the delivery order of
|
|
363
|
-
* every chain parked behind an unclaimed buffered hook payload
|
|
486
|
+
* every chain parked behind an unclaimed buffered hook payload: a hook the
|
|
364
487
|
* workflow never reads (a fire-and-forget `createHook`) parks every later
|
|
365
488
|
* armed wait/hook behind a barrier that only this net can retire. Per-barrier
|
|
366
489
|
* polls fire in whatever order their re-arm cycles land, and each re-arm
|
|
367
490
|
* attaches to a `promiseQueue` that grows between checks, so with several
|
|
368
491
|
* parked segments the release order decays to timing noise. Draws (`useStep`
|
|
369
|
-
* correlation ids) then depend on which segment happened to release first
|
|
492
|
+
* correlation ids) then depend on which segment happened to release first:
|
|
370
493
|
* concretely, on how MUCH log the replay loaded, since that decides what is in
|
|
371
494
|
* the registry. That is the mechanism behind slot-mode CORRUPTED_EVENT_LOG on
|
|
372
495
|
* storm-shaped runs (see storm-log-replay.test.ts, built from a production
|
|
@@ -376,12 +499,12 @@ const activeBarrierSafetyNets = new WeakSet();
|
|
|
376
499
|
* Retiring lowest-first is not merely tidy, it is the only order that cannot
|
|
377
500
|
* invert the log: every gate points from a higher index to a strictly lower
|
|
378
501
|
* one, so at delivery idle the lowest undelivered entry gates on nothing
|
|
379
|
-
* still registered
|
|
502
|
+
* still registered: it is the head of every parked chain (in practice, the
|
|
380
503
|
* unclaimed payload itself). Releasing it lets the chain above deliver
|
|
381
504
|
* through the ordinary barrier order; anything the release wakes flips
|
|
382
505
|
* {@link hasParkedCommittedDelivery} back to true, which re-blocks this
|
|
383
506
|
* dispenser until the chain has fully drained. A higher entry must never be
|
|
384
|
-
* retired while a lower one is registered
|
|
507
|
+
* retired while a lower one is registered, which is exactly the inversion
|
|
385
508
|
* described on {@link awaitEarlierDeliveries}.
|
|
386
509
|
*
|
|
387
510
|
* The dispenser goes dormant when the registry empties and is re-armed by the
|
|
@@ -418,16 +541,16 @@ function ensureBarrierSafetyNet(ctx) {
|
|
|
418
541
|
return;
|
|
419
542
|
}
|
|
420
543
|
// Idle with entries left: nothing remaining delivers on its own, so
|
|
421
|
-
// release parked chains from the head
|
|
544
|
+
// release parked chains from the head: lowest index first, one at a
|
|
422
545
|
// time, re-reading idle between retirements. A retirement that wakes a
|
|
423
546
|
// chain flips {@link hasParkedCommittedDelivery} synchronously (it is
|
|
424
547
|
// computed from the registry this loop just mutated), which stops the
|
|
425
548
|
// sweep so the chain delivers before anything above it is released. A
|
|
426
549
|
// retirement that wakes nothing (a stale payload no delivery gates on)
|
|
427
550
|
// 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.
|
|
551
|
+
// observation, since pacing them one per timer tick would hold
|
|
552
|
+
// consumed-but-undelivered events hostage long enough to trip the events
|
|
553
|
+
// consumer's unconsumed-event deadline and fail healthy replays.
|
|
431
554
|
while (barriers.size > 0 && canRetireAbandonedBarriers(ctx)) {
|
|
432
555
|
let lowestIndex;
|
|
433
556
|
let lowestEntry;
|
|
@@ -456,19 +579,19 @@ function canRetireAbandonedBarriers(ctx) {
|
|
|
456
579
|
/**
|
|
457
580
|
* Whether some registered branch-deciding delivery is going to reach the
|
|
458
581
|
* workflow without any further help (it is armed and not transitively parked
|
|
459
|
-
* behind an unclaimed buffered payload
|
|
582
|
+
* behind an unclaimed buffered payload, see {@link resolvesOnItsOwn}) but
|
|
460
583
|
* has not been handed over yet.
|
|
461
584
|
*
|
|
462
585
|
* This is the delivery state `pendingDeliveries` cannot see. That counter
|
|
463
586
|
* covers the hydration window inside a serial `promiseQueue` slot and is
|
|
464
587
|
* released there, while the delivery's `resolve()` runs later, from a
|
|
465
|
-
* detached continuation behind {@link awaitEarlierDeliveries}
|
|
588
|
+
* detached continuation behind {@link awaitEarlierDeliveries}, including its
|
|
466
589
|
* macrotask yield whenever the delivery had to defer. Replaying a batch of N
|
|
467
590
|
* parallel step results consumed in one drain window leaves N-1 of them
|
|
468
591
|
* parked on that yield with `pendingDeliveries` already at 0. An idle check
|
|
469
592
|
* armed during the same window (a pending `sleep()` arms one on every replay)
|
|
470
593
|
* could then observe "idle" mid-deferral and raise a `WorkflowSuspension`
|
|
471
|
-
* BEFORE the workflow's own continuations ran
|
|
594
|
+
* BEFORE the workflow's own continuations ran: a suspension carrying none of
|
|
472
595
|
* the follow-up work the batch was about to create, which the runtime
|
|
473
596
|
* dutifully schedules as nothing, leaving the run dormant until an unrelated
|
|
474
597
|
* timer fires (vercel/workflow#3183).
|
|
@@ -477,7 +600,7 @@ function canRetireAbandonedBarriers(ctx) {
|
|
|
477
600
|
* accuracy but for termination: an unclaimed buffered hook payload is retired
|
|
478
601
|
* BY the idle safety net in {@link registerDeliveryBarrier}, so counting it
|
|
479
602
|
* here would gate its own retirement. That reasoning extends to whatever is
|
|
480
|
-
* parked behind such a payload
|
|
603
|
+
* parked behind such a payload (a wait, and a step gating on that wait) for
|
|
481
604
|
* the same reason: the whole chain moves only once the net fires, and it
|
|
482
605
|
* cannot fire while the chain is counted. Self-resolving deliveries always
|
|
483
606
|
* deliver from their own chains (see the INVARIANT on
|
|
@@ -489,7 +612,7 @@ export function hasParkedCommittedDelivery(ctx) {
|
|
|
489
612
|
if (!barriers || barriers.size === 0) {
|
|
490
613
|
return false;
|
|
491
614
|
}
|
|
492
|
-
// Shared across this call only
|
|
615
|
+
// Shared across this call only. See `resolvesOnItsOwn`.
|
|
493
616
|
const selfResolving = new Map();
|
|
494
617
|
for (const [index, entry] of barriers) {
|
|
495
618
|
if (resolvesOnItsOwn(barriers, index, entry, selfResolving)) {
|
|
@@ -504,7 +627,7 @@ export function hasParkedCommittedDelivery(ctx) {
|
|
|
504
627
|
* "In flight" is two distinct windows, each with its own guard:
|
|
505
628
|
* `pendingDeliveries > 0` covers hydration inside the serial queue slots, and
|
|
506
629
|
* {@link hasParkedCommittedDelivery} covers the detached gap between a slot
|
|
507
|
-
* releasing that counter and the delivery's `resolve()` actually running
|
|
630
|
+
* releasing that counter and the delivery's `resolve()` actually running,
|
|
508
631
|
* deliberately outside `pendingDeliveries` (see step.ts), and invisible to it.
|
|
509
632
|
*
|
|
510
633
|
* Anything that decides a replay is over, or that a replay went wrong, has to
|
|
@@ -517,7 +640,7 @@ export function hasParkedCommittedDelivery(ctx) {
|
|
|
517
640
|
* entry is parked behind an unclaimed buffered payload. Those entries only
|
|
518
641
|
* move when the safety-net dispenser retires them (lowest-first, see
|
|
519
642
|
* {@link ensureBarrierSafetyNet}), and the deliveries they release are real
|
|
520
|
-
* workflow reactions
|
|
643
|
+
* workflow reactions: a suspension raised before they run would be computed
|
|
521
644
|
* from a VM that has not seen them, scheduling none of their follow-up work
|
|
522
645
|
* and leaving the run dormant (the vercel/workflow#3183 shape). The dispenser
|
|
523
646
|
* itself is gated on {@link canRetireAbandonedBarriers}, the weaker predicate
|
|
@@ -566,4 +689,13 @@ export function scheduleWhenIdle(ctx, fn) {
|
|
|
566
689
|
};
|
|
567
690
|
setTimeout(check, 0);
|
|
568
691
|
}
|
|
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==
|
|
692
|
+
/** Schedule a generation-guarded suspension after deliveries settle. */
|
|
693
|
+
export function scheduleWorkflowSuspension(ctx) {
|
|
694
|
+
const generation = ctx.suspensionGeneration;
|
|
695
|
+
scheduleWhenIdle(ctx, () => {
|
|
696
|
+
if (generation !== ctx.suspensionGeneration)
|
|
697
|
+
return;
|
|
698
|
+
ctx.onWorkflowError(new WorkflowSuspension(ctx.invocationsQueue, ctx.globalThis));
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJpdmF0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9wcml2YXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBRUgsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBR2hELE9BQU8sRUFBa0Isa0JBQWtCLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFhakUsTUFBTSxrQkFBa0IsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLGlDQUFpQyxDQUFDLENBQUM7QUFFekUsTUFBTSxhQUFhLEdBRWYsVUFBVSxDQUFDO0FBRWYsd0RBQXdEO0FBQ3hELE1BQU0sZUFBZSxHQUFHLENBQUMsYUFBYSxDQUFDLGtCQUFrQixDQUFDLEtBQUssSUFBSSxHQUFHLEVBR25FLENBQUMsQ0FBQztBQUVMLE1BQU0sMkJBQTJCLEdBQUcsSUFBSSxHQUFHLENBQUM7SUFDMUMsaUNBQWlDO0lBQ2pDLHlCQUF5QjtJQUN6Qix5QkFBeUI7Q0FDMUIsQ0FBQyxDQUFDO0FBRUgsU0FBUyx3QkFBd0IsQ0FBQyxNQUFjO0lBQzlDLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDakMsSUFBSSxLQUFLLENBQUMsTUFBTSxLQUFLLENBQUMsSUFBSSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssTUFBTSxFQUFFLENBQUM7UUFDOUMsT0FBTyxFQUFFLENBQUM7SUFDWixDQUFDO0lBRUQsTUFBTSxVQUFVLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzVCLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN4QixNQUFNLGlCQUFpQixHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7SUFFNUMsTUFBTSxRQUFRLEdBQUcsQ0FBQyxlQUF1QixFQUFFLEVBQUU7UUFDM0MsSUFBSSxlQUFlLEtBQUssVUFBVSxFQUFFLENBQUM7WUFDbkMsaUJBQWlCLENBQUMs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QUcsQ0FBQyxVQUFVLENBQUMsQ0FDN0QsQ0FBQztJQUNKLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVXRpbHMgdXNlZCBieSB0aGUgYnVuZGxlciB3aGVuIHRyYW5zZm9ybWluZyBjb2RlXG4gKi9cblxuaW1wb3J0IHsgd2l0aFJlc29sdmVycyB9IGZyb20gJ0B3b3JrZmxvdy91dGlscyc7XG5pbXBvcnQgdHlwZSB7IFdvcmxkQ2FwYWJpbGl0aWVzIH0gZnJvbSAnQHdvcmtmbG93L3dvcmxkJztcbmltcG9ydCB0eXBlIHsgRXZlbnRzQ29uc3VtZXIgfSBmcm9tICcuL2V2ZW50cy1jb25zdW1lci5qcyc7XG5pbXBvcnQgeyB0eXBlIFF1ZXVlSXRlbSwgV29ya2Zsb3dTdXNwZW5zaW9uIH0gZnJvbSAnLi9nbG9iYWwuanMnO1xuaW1wb3J0IHR5cGUgeyBSZXBsYXlQYXlsb2FkQ2FjaGUgfSBmcm9tICcuL3JlcGxheS1wYXlsb2FkLWNhY2hlLmpzJztcbmltcG9ydCB0eXBlIHsgU2VyaWFsaXphYmxlIH0gZnJvbSAnLi9zY2hlbWFzLmpzJztcbmltcG9ydCB0eXBlIHsgUGF5bG9hZEtleSB9IGZyb20gJy4vc2VyaWFsaXphdGlvbi9lbmNyeXB0aW9uLmpzJztcblxuZXhwb3J0IHR5cGUgU3RlcEZ1bmN0aW9uPFxuICBBcmdzIGV4dGVuZHMgU2VyaWFsaXphYmxlW10gPSBhbnlbXSxcbiAgUmVzdWx0IGV4dGVuZHMgU2VyaWFsaXphYmxlIHwgdW5rbm93biA9IHVua25vd24sXG4+ID0gKCguLi5hcmdzOiBBcmdzKSA9PiBQcm9taXNlPFJlc3VsdD4pICYge1xuICBtYXhSZXRyaWVzPzogbnVtYmVyO1xuICBzdGVwSWQ/OiBzdHJpbmc7XG59O1xuXG5jb25zdCBSZWdpc3RlcmVkU3RlcHNLZXkgPSBTeW1ib2wuZm9yKCdAd29ya2Zsb3cvY29yZS8vcmVnaXN0ZXJlZFN0ZXBzJyk7XG5cbmNvbnN0IGdsb2JhbFN5bWJvbHM6IHR5cGVvZiBnbG9iYWxUaGlzICYge1xuICBbUmVnaXN0ZXJlZFN0ZXBzS2V5XT86IE1hcDxzdHJpbmcsIFN0ZXBGdW5jdGlvbj47XG59ID0gZ2xvYmFsVGhpcztcblxuLy8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy9ub0Fzc2lnbkluRXhwcmVzc2lvbnM6IC9cbmNvbnN0IHJlZ2lzdGVyZWRTdGVwcyA9IChnbG9iYWxTeW1ib2xzW1JlZ2lzdGVyZWRTdGVwc0tleV0gPz89IG5ldyBNYXA8XG4gIHN0cmluZyxcbiAgU3RlcEZ1bmN0aW9uXG4+KCkpO1xuXG5jb25zdCBCVUlMVElOX1JFU1BPTlNFX1NURVBfTkFNRVMgPSBuZXcgU2V0KFtcbiAgJ19fYnVpbHRpbl9yZXNwb25zZV9hcnJheV9idWZmZXInLFxuICAnX19idWlsdGluX3Jlc3BvbnNlX2pzb24nLFxuICAnX19idWlsdGluX3Jlc3BvbnNlX3RleHQnLFxuXSk7XG5cbmZ1bmN0aW9uIGdldFN0ZXBJZEFsaWFzQ2FuZGlkYXRlcyhzdGVwSWQ6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgY29uc3QgcGFydHMgPSBzdGVwSWQuc3BsaXQoJy8vJyk7XG4gIGlmIChwYXJ0cy5sZW5ndGggIT09IDMgfHwgcGFydHNbMF0gIT09ICdzdGVwJykge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIGNvbnN0IG1vZHVsZVBhdGggPSBwYXJ0c1sxXTtcbiAgY29uc3QgZm5OYW1lID0gcGFydHNbMl07XG4gIGNvbnN0IG1vZHVsZVBhdGhBbGlhc2VzID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgY29uc3QgYWRkQWxpYXMgPSAoYWxpYXNNb2R1bGVQYXRoOiBzdHJpbmcpID0+IHtcbiAgICBpZiAoYWxpYXNNb2R1bGVQYXRoICE9PSBtb2R1bGVQYXRoKSB7XG4gICAgICBtb2R1bGVQYXRoQWxpYXNlcy5hZGQoYWxpYXNNb2R1bGVQYXRoKTtcbiAgICB9XG4gIH07XG5cbiAgaWYgKG1vZHVsZVBhdGguc3RhcnRzV2l0aCgnLi93b3JrZmxvd3MvJykpIHtcbiAgICBjb25zdCB3b3JrZmxvd1JlbGF0aXZlUGF0aCA9IG1vZHVsZVBhdGguc2xpY2UoJy4vJy5sZW5ndGgpO1xuICAgIGFkZEFsaWFzKGAuL2V4YW1wbGUvJHt3b3JrZmxvd1JlbGF0aXZlUGF0aH1gKTtcbiAgICBhZGRBbGlhcyhgLi9zcmMvJHt3b3JrZmxvd1JlbGF0aXZlUGF0aH1gKTtcbiAgfSBlbHNlIGlmIChtb2R1bGVQYXRoLnN0YXJ0c1dpdGgoJy4vZXhhbXBsZS93b3JrZmxvd3MvJykpIHtcbiAgICBjb25zdCB3b3JrZmxvd1JlbGF0aXZlUGF0aCA9IG1vZHVsZVBhdGguc2xpY2UoJy4vZXhhbXBsZS8nLmxlbmd0aCk7XG4gICAgYWRkQWxpYXMoYC4vJHt3b3JrZmxvd1JlbGF0aXZlUGF0aH1gKTtcbiAgICBhZGRBbGlhcyhgLi9zcmMvJHt3b3JrZmxvd1JlbGF0aXZlUGF0aH1gKTtcbiAgfSBlbHNlIGlmIChtb2R1bGVQYXRoLnN0YXJ0c1dpdGgoJy4vc3JjL3dvcmtmbG93cy8nKSkge1xuICAgIGNvbnN0IHdvcmtmbG93UmVsYXRpdmVQYXRoID0gbW9kdWxlUGF0aC5zbGljZSgnLi9zcmMvJy5sZW5ndGgpO1xuICAgIGFkZEFsaWFzKGAuLyR7d29ya2Zsb3dSZWxhdGl2ZVBhdGh9YCk7XG4gICAgYWRkQWxpYXMoYC4vZXhhbXBsZS8ke3dvcmtmbG93UmVsYXRpdmVQYXRofWApO1xuICB9XG5cbiAgcmV0dXJuIEFycmF5LmZyb20oXG4gICAgbW9kdWxlUGF0aEFsaWFzZXMsXG4gICAgKGFsaWFzTW9kdWxlUGF0aCkgPT4gYHN0ZXAvLyR7YWxpYXNNb2R1bGVQYXRofS8vJHtmbk5hbWV9YFxuICApO1xufVxuXG5mdW5jdGlvbiBnZXRCdWlsdGluUmVzcG9uc2VTdGVwQWxpYXMoc3RlcElkOiBzdHJpbmcpOiBTdGVwRnVuY3Rpb24gfCB1bmRlZmluZWQge1xuICBpZiAoIUJVSUxUSU5fUkVTUE9OU0VfU1RFUF9OQU1FUy5oYXMoc3RlcElkKSkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBmb3IgKGNvbnN0IFtyZWdpc3RlcmVkU3RlcElkLCBzdGVwRm5dIG9mIHJlZ2lzdGVyZWRTdGVwcy5lbnRyaWVzKCkpIHtcbiAgICBpZiAocmVnaXN0ZXJlZFN0ZXBJZC5lbmRzV2l0aChgLy8ke3N0ZXBJZH1gKSkge1xuICAgICAgcmV0dXJuIHN0ZXBGbjtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVyIGEgc3RlcCBmdW5jdGlvbiB0byBiZSBzZXJ2ZWQgaW4gdGhlIHNlcnZlciBidW5kbGUuXG4gKiBBbHNvIHNldHMgdGhlIHN0ZXBJZCBwcm9wZXJ0eSBvbiB0aGUgZnVuY3Rpb24gZm9yIHNlcmlhbGl6YXRpb24gc3VwcG9ydC5cbiAqXG4gKiBOb3RlOiBUaGUgU1dDIGNvbXBpbGVyIHBsdWdpbiBubyBsb25nZXIgZ2VuZXJhdGVzIGNhbGxzIHRvIHRoaXMgZnVuY3Rpb24uXG4gKiBTdGVwIHJlZ2lzdHJhdGlvbiBpcyBub3cgaW5saW5lZCBhcyBhIHNlbGYtY29udGFpbmVkIElJRkUgdGhhdCB3cml0ZXNcbiAqIGRpcmVjdGx5IHRvIHRoZSBnbG9iYWwgTWFwIGF0IFN5bWJvbC5mb3IoXCJAd29ya2Zsb3cvY29yZS8vcmVnaXN0ZXJlZFN0ZXBzXCIpLlxuICogVGhpcyBmdW5jdGlvbiBpcyBrZXB0IGZvciBpbnRlcm5hbC90ZXN0IHVzZSBvbmx5LlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJTdGVwRnVuY3Rpb24oc3RlcElkOiBzdHJpbmcsIHN0ZXBGbjogU3RlcEZ1bmN0aW9uKSB7XG4gIHJlZ2lzdGVyZWRTdGVwcy5zZXQoc3RlcElkLCBzdGVwRm4pO1xuICBzdGVwRm4uc3RlcElkID0gc3RlcElkO1xufVxuXG4vKipcbiAqIEZpbmQgYSByZWdpc3RlcmVkIHN0ZXAgZnVuY3Rpb24gYnkgbmFtZVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0U3RlcEZ1bmN0aW9uKHN0ZXBJZDogc3RyaW5nKTogU3RlcEZ1bmN0aW9uIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgZGlyZWN0TWF0Y2ggPSByZWdpc3RlcmVkU3RlcHMuZ2V0KHN0ZXBJZCk7XG4gIGlmIChkaXJlY3RNYXRjaCkge1xuICAgIHJldHVybiBkaXJlY3RNYXRjaDtcbiAgfVxuXG4gIC8vIFN1cHBvcnQgZXF1aXZhbGVudCB3b3JrZmxvdyBwYXRoIGFsaWFzZXMgaW4gbWl4ZWQgc3ltbGluayBlbnZpcm9ubWVudHMuXG4gIGZvciAoY29uc3QgYWxpYXNTdGVwSWQgb2YgZ2V0U3RlcElkQWxpYXNDYW5kaWRhdGVzKHN0ZXBJZCkpIHtcbiAgICBjb25zdCBhbGlhc01hdGNoID0gcmVnaXN0ZXJlZFN0ZXBzLmdldChhbGlhc1N0ZXBJZCk7XG4gICAgaWYgKGFsaWFzTWF0Y2gpIHtcbiAgICAgIHJldHVybiBhbGlhc01hdGNoO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IGJ1aWx0aW5BbGlhc01hdGNoID0gZ2V0QnVpbHRpblJlc3BvbnNlU3RlcEFsaWFzKHN0ZXBJZCk7XG4gIGlmIChidWlsdGluQWxpYXNNYXRjaCkge1xuICAgIHJldHVybiBidWlsdGluQWxpYXNNYXRjaDtcbiAgfVxuXG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbi8vIE5vdGU6IF9fcHJpdmF0ZV9nZXRDbG9zdXJlVmFycyBpcyBubyBsb25nZXIgcmUtZXhwb3J0ZWQgaGVyZS5cbi8vIFRoZSBTV0MgY29tcGlsZXIgcGx1Z2luIG5vdyBpbmxpbmVzIGNsb3N1cmUgdmFyaWFibGUgYWNjZXNzIGFzIGFcbi8vIHNlbGYtY29udGFpbmVkIElJRkUgdGhhdCByZWFkcyBkaXJlY3RseSBmcm9tIHRoZSBnbG9iYWwgQXN5bmNMb2NhbFN0b3JhZ2Vcbi8vIGF0IFN5bWJvbC5mb3IoXCJXT1JLRkxPV19TVEVQX0NPTlRFWFRfU1RPUkFHRVwiKS5cblxuZXhwb3J0IGludGVyZmFjZSBXb3JrZmxvd09yY2hlc3RyYXRvckNvbnRleHQge1xuICBydW5JZDogc3RyaW5nO1xuICBlbmNyeXB0aW9uS2V5OiBQYXlsb2FkS2V5IHwgdW5kZWZpbmVkO1xuICB3b3JsZENhcGFiaWxpdGllcz86IFdvcmxkQ2FwYWJpbGl0aWVzO1xuICBnbG9iYWxUaGlzOiB0eXBlb2YgZ2xvYmFsVGhpcztcbiAgLyoqXG4gICAqIEluY3JlbWVudHMgd2hlbiBhIHN1c3BlbnNpb24gaXMgYWNjZXB0ZWQgYW5kIG9uIGV2ZXJ5IHJldGFpbmVkLXNlc3Npb25cbiAgICogcmVzdW1lLiBTdGVwLCBob29rLCBhbmQgYXR0cmlidXRlIHN1c3BlbnNpb24gc2lnbmFscyBjYXB0dXJlIGl0IHdoZW5cbiAgICogc2NoZWR1bGVkIGFuZCBuby1vcCBpZiBpdCBtb3ZlZCwgd2hpY2ggZHJvcHMgc2FtZS1ib3VuZGFyeSBzaWJsaW5nIHNpZ25hbHNcbiAgICogYW5kIHRpbWVycyBxdWV1ZWQgYXQgYm91bmRhcnkgTiB0aGF0IHdvdWxkIGZpcmUgYWZ0ZXIgdGhlIHNlc3Npb24gcmVzdW1lZFxuICAgKiBpbnRvIGJvdW5kYXJ5IE4rMS4gU2xlZXAgc2lnbmFscyBhcmUgaW50ZW50aW9uYWxseSB1bmd1YXJkZWQ6IHRoZWlyXG4gICAqIHByZXNlbmNlIG1ha2VzIHRoZSBib3VuZGFyeSB1bnJldGFpbmFibGUsIHNvIGEgbGF0ZSBzaWduYWwgY29ycmVjdGx5XG4gICAqIGRlbW90ZXMgdGhlIHNlc3Npb24gKHdvcmtmbG93LnRzIGBvbldvcmtmbG93RXJyb3JgKS5cbiAgICovXG4gIHN1c3BlbnNpb25HZW5lcmF0aW9uOiBudW1iZXI7XG4gIGV2ZW50c0NvbnN1bWVyOiBFdmVudHNDb25zdW1lcjtcbiAgLyoqXG4gICAqIE1hcCBvZiBwZW5kaW5nIGludm9jYXRpb25zIGtleWVkIGJ5IGNvcnJlbGF0aW9uSWQuXG4gICAqIFVzaW5nIE1hcCBpbnN0ZWFkIG9mIEFycmF5IGZvciBPKDEpIGxvb2t1cC9kZWxldGUgb3BlcmF0aW9ucy5cbiAgICovXG4gIGludm9jYXRpb25zUXVldWU6IE1hcDxzdHJpbmcsIFF1ZXVlSXRlbT47XG4gIG9uV29ya2Zsb3dFcnJvcjogKGVycm9yOiBFcnJvcikgPT4gdm9pZDtcbiAgLyoqXG4gICAqIE1pbnRzIHRoZSBVTElEIGJvZHkgb2YgYSBjb3JyZWxhdGlvbiBpZC4gRXZlcnkgZW50aXR5IGEgcmVwbGF5IGNyZWF0ZXNcbiAgICogZHJhd3MgZnJvbSB0aGlzIG9uZSBtb25vdG9uaWMgc2VxdWVuY2UsIHNvIGFuIGlkIGlzIGFuIG9yZGluYWwgb3ZlciB0aGVcbiAgICogd2hvbGUgcnVuIGFuZCBib3RoIHJlcGxheXMgb2YgYSBydW4gbXVzdCBkcmF3IGluIHRoZSBzYW1lIG9yZGVyLlxuICAgKi9cbiAgZ2VuZXJhdGVVbGlkOiAoKSA9PiBzdHJpbmc7XG4gIC8qKlxuICAgKiBNb25vdG9uZSBjb3VudCBvZiBjb3JyZWxhdGlvbi1pZCBkcmF3cyB0aGlzIHJlcGxheSBoYXMgbWFkZS4gUHJvZ3Jlc3NcbiAgICogbWV0cmljIGZvciB7QGxpbmsgcXVpZXNjZUVhcmxpZXJDYXNjYWRlc306IGEgbWFjcm90YXNrIHR1cm4gaW4gd2hpY2ggaXRcbiAgICogZG9lcyBub3QgbW92ZSAoYW5kIG5vIGh5ZHJhdGlvbiBpcyBpbiBmbGlnaHQpIG1lYW5zIGV2ZXJ5IHdva2VuIGJyYW5jaCBoYXNcbiAgICogcnVuIGFzIGZhciBhcyBpdCBjYW4gd2l0aG91dCBhbm90aGVyIGRlbGl2ZXJ5LiBPcHRpb25hbCBzbyBsaWdodHdlaWdodFxuICAgKiB0ZXN0IGNvbnRleHRzIGRlZ3JhZGUgdG8gdGhlIHNpbmdsZS15aWVsZCBiZWhhdmlvci5cbiAgICovXG4gIHJlYWRvbmx5IG1pbnRDb3VudD86IG51bWJlcjtcbiAgZ2VuZXJhdGVOYW5vaWQ6ICgpID0+IHN0cmluZztcbiAgLyoqXG4gICAqIFNlcXVlbnRpYWwgcHJvbWlzZSBxdWV1ZSB0aGF0IGVuc3VyZXMgYWxsIGV2ZW50LWRyaXZlbiBwcm9taXNlIHJlc29sdXRpb25zXG4gICAqIChzdGVwIHJlc3VsdHMsIGhvb2sgcGF5bG9hZHMsIGZhaWx1cmVzLCBzdXNwZW5zaW9ucykgaGFwcGVuIGluIGV2ZW50IGxvZ1xuICAgKiBvcmRlci4gRXZlcnkgcmVzb2x2ZSwgcmVqZWN0LCBvciB3b3JrZmxvdyBlcnJvciBpcyBjaGFpbmVkIHRocm91Z2ggdGhpc1xuICAgKiBxdWV1ZSBzbyB0aGF0IGV2ZW4gaWYgaW5kaXZpZHVhbCBvcGVyYXRpb25zIHRha2UgdmFyaWFibGUgdGltZSAoZS5nLixcbiAgICogYXN5bmMgZGVjcnlwdGlvbiksIHByb21pc2VzIHJlc29sdmUgZGV0ZXJtaW5pc3RpY2FsbHkuXG4gICAqL1xuICBwcm9taXNlUXVldWU6IFByb21pc2U8dm9pZD47XG4gIC8qKlxuICAgKiBDb3VudGVyIG9mIGluLWZsaWdodCBhc3luYyBkYXRhIGRlbGl2ZXJ5IG9wZXJhdGlvbnMgKHN0ZXAgcmVzdWx0XG4gICAqIGh5ZHJhdGlvbiwgaG9vayBwYXlsb2FkIGh5ZHJhdGlvbiwgYWJvcnQgc2lnbmFsIGh5ZHJhdGlvbikuIFN1c3BlbnNpb25zXG4gICAqIG11c3Qgd2FpdCBmb3IgdGhpcyB0byByZWFjaCAwIGJlZm9yZSBmaXJpbmcsIHRvIGF2b2lkIHByZWVtcHRpbmcgZGF0YVxuICAgKiBkZWxpdmVyeSwgZS5nLiBkZWh5ZHJhdGluZyBhIHN0ZXAncyBhcmd1bWVudHMgd2hpbGUgYW4gYWJvcnQgdGhhdCBzaG91bGRcbiAgICogYmUgcmVmbGVjdGVkIGluIHRob3NlIGFyZ3VtZW50cyBpcyBzdGlsbCBoeWRyYXRpbmcgaXRzIHJlYXNvbi5cbiAgICovXG4gIHBlbmRpbmdEZWxpdmVyaWVzOiBudW1iZXI7XG4gIC8qKlxuICAgKiBPcmRlcmVkIHJlZ2lzdHJ5IG9mIGluLWZsaWdodCBcImJyYW5jaC1kZWNpZGluZ1wiIGRlbGl2ZXJpZXM6IHRoZVxuICAgKiByZXNvbHV0aW9ucyBhIHdvcmtmbG93IHR5cGljYWxseSBgUHJvbWlzZS5yYWNlYHMgb24sIG9yIGF3YWl0cyBmcm9tXG4gICAqIGluZGVwZW5kZW50IGNvbmN1cnJlbnQgYnJhbmNoZXM6IGhvb2sgcGF5bG9hZHMgKGBob29rX3JlY2VpdmVkYCksIHdhaXRcbiAgICogY29tcGxldGlvbnMgKGB3YWl0X2NvbXBsZXRlZGApLCBhbmQgc3RlcCByZXN1bHRzIChgc3RlcF9jb21wbGV0ZWRgIC9cbiAgICogYHN0ZXBfZmFpbGVkYCkuIEtleWVkIGJ5IHRoZSBkZWxpdmVyeSdzIHBvc2l0aW9uIChpbmRleCkgaW4gdGhlIGNvbnN1bWVkXG4gICAqIGV2ZW50IGxvZy5cbiAgICpcbiAgICogVGhlIHByb2JsZW06IGVhY2ggb2YgdGhlc2UgcmVzb2x1dGlvbnMgcmVhY2hlcyB3b3JrZmxvdyBjb2RlIGFmdGVyIGFcbiAgICogZGlmZmVyZW50LCB3b3JrbG9hZC1kZXBlbmRlbnQgbnVtYmVyIG9mIG1pY3JvdGFzayBob3BzLiBBIGJ1ZmZlcmVkIGhvb2tcbiAgICogcGF5bG9hZCBpcyBvYnNlcnZlZCB2aWEgdGhlIGFzeW5jIGhvb2sgaXRlcmF0b3IgKGB5aWVsZCBhd2FpdCB0aGlzYCksXG4gICAqIGNvc3RpbmcgZXh0cmEgaG9wczsgYSBgd2FpdF9jb21wbGV0ZWRgIHJlc29sdmVzIHdpdGggZmV3ZXIsIGFuZCBhIHJldXNlZFxuICAgKiBzbGVlcCBjYW4gcmVzb2x2ZSBpbiBhbiBlbnRpcmVseSBlYXJsaWVyIGxvb3AgaXRlcmF0aW9uOyBhIHN0ZXAgcmVzdWx0IGlzXG4gICAqIGdhdGVkIG9uIGh5ZHJhdGlvbiB3aG9zZSBjb3N0IHZhcmllcyBiZXR3ZWVuIHJlcGxheXMgb2YgdGhlIFNBTUVcbiAgICogaW52b2NhdGlvbjogdGhlIGZpcnN0IHJlcGxheSBwYXlzIHRoZSBmdWxsIGRlY3J5cHQvZGVjb21wcmVzcy9yZXZpdmUsXG4gICAqIHdoaWxlIGxhdGVyIHJlcGxheXMgc2hhcmluZyB0aGUgaW52b2NhdGlvbidzIGBSZXBsYXlQYXlsb2FkQ2FjaGVgXG4gICAqIG1lbW8taGl0IHNtYWxsIHByaW1pdGl2ZSByZXN1bHRzIGFuZCByZXNvbHZlIGluIG9uZSBvciB0d28gaG9wcy4gRWl0aGVyXG4gICAqIHdheSwgdGhlIHJlc29sdXRpb24gdGhhdCB0aGUgY29tbWl0dGVkIGV2ZW50IGxvZyBvcmRlcmVkIGZpcnN0IGNhbiBsb3NlIGFcbiAgICogYFByb21pc2UucmFjZWAgKG9yIGEgYHVzZVN0ZXBgIFVMSUQgYWxsb2NhdGlvbikgdG8gYSBmYXN0ZXItIG9yXG4gICAqIGFscmVhZHktcmVzb2x2ZWQgY29tcGV0aXRvciwgZGl2ZXJnaW5nIGZyb20gdGhlIGxvZyBhbmQgc3VyZmFjaW5nIGFzXG4gICAqIGBDb3JydXB0ZWRFdmVudExvZ0Vycm9yYC5cbiAgICpcbiAgICogVGhlIGZpeCBpcyBhIHN0cmljdCwgZGV0ZXJtaW5pc3RpYyBkZWxpdmVyeSBvcmRlciBhbmNob3JlZCBvblxuICAgKiBldmVudC1sb2cgcG9zaXRpb246IGEgZGVsaXZlcnkgZG9lcyBub3QgcmVzb2x2ZSB0byB0aGUgd29ya2Zsb3cgdW50aWxcbiAgICogZXZlcnkgcmVsZXZhbnQgZWFybGllci1pbi1sb2cgZGVsaXZlcnkgaGFzIGJlZW4gZGVsaXZlcmVkLiBCZWNhdXNlIHRoZVxuICAgKiBnYXRlIGlzIFwidGhlIGVhcmxpZXIgZGVsaXZlcnkgcmVzb2x2ZWRcIiwgbm90IFwid29uIGEgdGltaW5nIHJhY2VcIiwgdGhlXG4gICAqIG91dGNvbWUgaXMgaW5kZXBlbmRlbnQgb2YgbWljcm90YXNrIGhvcHMsIGh5ZHJhdGlvbi9kZWNyeXB0aW9uIHRpbWUsXG4gICAqIGFuZCBgUHJvbWlzZS5yYWNlYCBhcmd1bWVudCBvcmRlci4gV2hpY2ggZWFybGllciBraW5kcyBhIGRlbGl2ZXJ5IGRlZmVyc1xuICAgKiBiZWhpbmQgaXMgc3BlbGxlZCBvdXQgb24ge0BsaW5rIGF3YWl0RWFybGllckRlbGl2ZXJpZXN9LlxuICAgKlxuICAgKiBJbmRleCBpcyB1c2VkIHJhdGhlciB0aGFuIHRoZSBgZXZlbnRJZGAgc3RyaW5nIGJlY2F1c2UgYGV2ZW50SWRgIGlzIGFuXG4gICAqIG9wYXF1ZSwgd29ybGQtYXNzaWduZWQgdmFsdWUgbm90IGd1YXJhbnRlZWQgdG8gc29ydCBpbiBjcmVhdGlvbiBvcmRlclxuICAgKiAob25seSB0aGUgYnVuZGxlZCBVTElEIHdvcmxkcyBoYXBwZW4gdG8pLlxuICAgKlxuICAgKiBPcHRpb25hbCBzbyBvbGRlci9vdXQtb2YtdHJlZSBjb250ZXh0cyAoYW5kIGxpZ2h0d2VpZ2h0IHRlc3QgaGFybmVzc2VzKVxuICAgKiB0aGF0IGRvIG5vdCBpbml0aWFsaXplIGl0IGRlZ3JhZGUgZ3JhY2VmdWxseSB0byB0aGUgcHJldmlvdXMgYmVoYXZpb3IuXG4gICAqL1xuICBwZW5kaW5nRGVsaXZlcnlCYXJyaWVycz86IE1hcDxudW1iZXIsIERlbGl2ZXJ5QmFycmllckVudHJ5PjtcbiAgLyoqXG4gICAqIEludm9jYXRpb24tc2NvcGVkIGNhY2hlIG9mIHByZXBhcmVkIHNlcmlhbGl6ZWQgcGF5bG9hZHMgYW5kIGltbXV0YWJsZSBmaW5hbFxuICAgKiB2YWx1ZXMuIFByZXBhcmVkIGJ5dGVzIHN1cnZpdmUgZnJlc2ggcmVwbGF5IFZNczsgb2JqZWN0IGdyYXBocyBkbyBub3QuXG4gICAqL1xuICByZXBsYXlQYXlsb2FkQ2FjaGU6IFJlcGxheVBheWxvYWRDYWNoZTtcbn1cblxuLyoqIFRoZSBraW5kIG9mIGJyYW5jaC1kZWNpZGluZyBkZWxpdmVyeSBhIGJhcnJpZXIgcmVwcmVzZW50cy4gKi9cbmV4cG9ydCB0eXBlIERlbGl2ZXJ5S2luZCA9ICdob29rJyB8ICd3YWl0JyB8ICdzdGVwJztcblxuaW50ZXJmYWNlIERlbGl2ZXJ5QmFycmllckVudHJ5IHtcbiAga2luZDogRGVsaXZlcnlLaW5kO1xuICAvKiogUmVzb2x2ZXMgb25jZSB0aGlzIGRlbGl2ZXJ5IGhhcyByZXNvbHZlZCB0byB0aGUgd29ya2Zsb3cuICovXG4gIGRlbGl2ZXJlZDogUHJvbWlzZTx2b2lkPjtcbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhpcyBkZWxpdmVyeSBpcyBjb21taXR0ZWQgdG8gcmVhY2hpbmcgdGhlIHdvcmtmbG93IHdpdGhvdXQgYW55XG4gICAqIGZ1cnRoZXIgYWN0aW9uIGJ5IHdvcmtmbG93IGNvZGUuIFRydWUgZm9yIHdhaXQgY29tcGxldGlvbnMgYW5kIHN0ZXBcbiAgICogcmVzdWx0cywgd2hpY2ggYWx3YXlzIHJlc29sdmUgZnJvbSB0aGVpciBvd24gY2hhaW4sIGFuZCBmb3IgYSBob29rIHBheWxvYWRcbiAgICogdGhhdCBhbHJlYWR5IGhhZCBhIHdhaXRpbmcgY29uc3VtZXIgd2hlbiBpdCB3YXMgY29uc3VtZWQuXG4gICAqXG4gICAqIEZhbHNlIGZvciBhIEJVRkZFUkVEIGhvb2sgcGF5bG9hZCBubyBjb25zdW1lciBoYXMgY2xhaW1lZCB5ZXQ6IGl0IGlzXG4gICAqIGRlbGl2ZXJlZCBieSBgY2xhaW0oKWAsIGkuZS4gd2hlbmV2ZXIgdGhlIHdvcmtmbG93IG5leHQgcmVhZHMgdGhlIGhvb2ssXG4gICAqIHdoaWNoIG1heSBiZSBjYXVzYWxseSAqYWZ0ZXIqIGEgbGF0ZXItaW4tbG9nIGRlbGl2ZXJ5LiBgYXJtKClgIGZsaXBzIGl0XG4gICAqIG9uY2UgYSBjb25zdW1lciB0YWtlcyB0aGUgcGF5bG9hZC5cbiAgICovXG4gIGFybWVkOiBib29sZWFuO1xuICAvKipcbiAgICogUmV0aXJlIHRoaXMgZW50cnk6IHJlc29sdmUgYGRlbGl2ZXJlZGAgYW5kIHJlbW92ZSBpdCBmcm9tIHRoZSByZWdpc3RyeSxcbiAgICogZXhhY3RseSBhcyBgbWFya0RlbGl2ZXJlZGAgd291bGQuIENhbGxlZCBvbmx5IGJ5IHRoZSBjb250ZXh0J3Mgc2FmZXR5LW5ldFxuICAgKiBkaXNwZW5zZXIgKHtAbGluayBlbnN1cmVCYXJyaWVyU2FmZXR5TmV0fSksIGFuZCBvbmx5IG9uIHRoZSBsb3dlc3QtaW5kZXhcbiAgICogZW50cnkgYXQgZGVsaXZlcnkgaWRsZS4gSWRlbXBvdGVudC5cbiAgICovXG4gIHJldGlyZTogKCkgPT4gdm9pZDtcbn1cblxuLyoqXG4gKiBXaGljaCBlYXJsaWVyIGtpbmRzIGVhY2ggZGVsaXZlcnkga2luZCBkZWZlcnMgYmVoaW5kLiBDaG9zZW4gc28gdGhhdCBubyBraW5kXG4gKiBibG9ja3Mgb24gYSBwZWVyIGl0IGRvZXMgbm90IG5lZWQgdG86XG4gKlxuICogIC0gYSBob29rIGRlZmVycyBiZWhpbmQgZWFybGllciBIT09LUywgV0FJVFMgYW5kIFNURVBTO1xuICogIC0gYSB3YWl0IGRlZmVycyBiZWhpbmQgZWFybGllciBIT09LUyBhbmQgU1RFUFMgKG5vdCBlYXJsaWVyIHdhaXRzLCBzaW5jZSBhXG4gKiAgICB3YWl0IG5ldmVyIG5lZWRzIHRvIHF1ZXVlIGJlaGluZCBhbm90aGVyIHdhaXQpO1xuICogIC0gYSBzdGVwIGRlZmVycyBiZWhpbmQgZWFybGllciBXQUlUUywgSE9PS1MgYW5kIFNURVBTLlxuICpcbiAqIFRoZSBzdGVwLWJlaGluZC1zdGVwIGVkZ2UgaXMgbm90IHJlZHVuZGFudCB3aXRoIHRoZSBzZXJpYWwgYHByb21pc2VRdWV1ZWAuXG4gKiBUaGUgcXVldWUgZml4ZXMgdGhlIG9yZGVyIGluIHdoaWNoIHN0ZXAgcmVzdWx0cyBhcmUgSFlEUkFURUQsIGJ1dCBhIHN0ZXAgbm9cbiAqIGxvbmdlciByZXNvbHZlcyBpbnNpZGUgaXRzIHF1ZXVlIHNsb3Q6IGl0IGNhcHR1cmVzIHRoZSBvdXRjb21lIHRoZXJlIGFuZFxuICogcmVzb2x2ZXMgZnJvbSBhIGRldGFjaGVkIGNvbnRpbnVhdGlvbiBvbmNlIGl0cyBiYXJyaWVyIGNsZWFycy4gVHdvIHN0ZXBzXG4gKiBhZ3JlZSBvbiB0aGF0IGNvbnRpbnVhdGlvbidzIG9yZGVyaW5nIG9ubHkgd2hpbGUgdGhleSBkZWZlciBiZWhpbmQgdGhlIHNhbWVcbiAqIHNldCwgd2hpY2ggaG9sZHMgd2hlbiB0aGV5IGFyZSBjb25zdW1lZCBpbiB0aGUgc2FtZSBkcmFpbiB3aW5kb3cgYnV0IG5vdFxuICogYWNyb3NzIHdpbmRvd3M6IGEgc3RlcCBjb25zdW1lZCBsYXRlciBjYW4gbWlzcyBhIHdhaXQvaG9vayBiYXJyaWVyIHRoYXQgYW5cbiAqIGVhcmxpZXIgc3RlcCBpcyBzdGlsbCBwYXJrZWQgb24sIGJlY2F1c2UgdGhlIGJhcnJpZXIgcmV0aXJlZCBpbiBiZXR3ZWVuLiBUaGVcbiAqIGVhcmxpZXIgc3RlcCBpcyB0aGVuIHdhaXRpbmcgb3V0IHRoZSBtYWNyb3Rhc2sgeWllbGQgYmVsb3cgd2hpbGUgdGhlIGxhdGVyXG4gKiBvbmUgcmVzb2x2ZXMgb24gbWljcm90YXNrcywgYW5kIG92ZXJ0YWtlcyBpdC4gU2VlXG4gKiBgZGVsaXZlcnktYmFycmllci1jb3ZlcmFnZS50ZXN0LnRzYC4gRGVmZXJyaW5nIGJlaGluZCBlYXJsaWVyIHN0ZXBzXG4gKiBjbG9zZXMgdGhhdCB3aW5kb3cgc3RydWN0dXJhbGx5OiB0aGUgZWFybGllciBzdGVwJ3MgYmFycmllciBpcyBzdGlsbFxuICogcmVnaXN0ZXJlZCBwcmVjaXNlbHkgYmVjYXVzZSBpdCBoYXMgbm90IGRlbGl2ZXJlZCB5ZXQuXG4gKlxuICogRXZlcnkgZWRnZSBwb2ludHMgZnJvbSBhIGxhdGVyIGxvZyBpbmRleCB0byBhIHN0cmljdGx5IGVhcmxpZXIgb25lLCBzbyB0aGVcbiAqIHdhaXQtZm9yIGdyYXBoIGNhbiBuZXZlciBjb250YWluIGEgY3ljbGUuXG4gKi9cbmNvbnN0IERFRkVSX0JFSElORDogUmVjb3JkPERlbGl2ZXJ5S2luZCwgcmVhZG9ubHkgRGVsaXZlcnlLaW5kW10+ID0ge1xuICBob29rOiBbJ2hvb2snLCAnd2FpdCcsICdzdGVwJ10sXG4gIHdhaXQ6IFsnaG9vaycsICdzdGVwJ10sXG4gIHN0ZXA6IFsnd2FpdCcsICdob29rJywgJ3N0ZXAnXSxcbn07XG5cbi8qKlxuICogV2hldGhlciBhIGRlbGl2ZXJ5IG9mIGBraW5kYCBhdCBsb2cgaW5kZXggYGluZGV4YCBnYXRlcyBvbiB0aGUgZWFybGllclxuICogcmVnaXN0cnkgZW50cnkgYG90aGVyYCAoYXQgYG90aGVySW5kZXhgKS5cbiAqXG4gKiBTaW5nbGUgc291cmNlIG9mIHRydXRoIGZvciB0aGF0IHF1ZXN0aW9uLCBjYWxsZWQgYnkgYm90aFxuICoge0BsaW5rIGF3YWl0RWFybGllckRlbGl2ZXJpZXN9ICh3aGljaCBhd2FpdHMgd2hhdCBpdCBnYXRlcyBvbikgYW5kXG4gKiB7QGxpbmsgY29tcHV0ZVJlc29sdmVzT25JdHNPd259ICh3aGljaCByZWN1cnNlcyBpbnRvIHdoYXQgaXQgZ2F0ZXMgb24pLlxuICogVGhvc2UgdHdvIE1VU1QgYWdyZWUgZXhhY3RseSwgYW5kIHRoZSBkb2MgYmxvY2sgb25cbiAqIHtAbGluayBhd2FpdEVhcmxpZXJEZWxpdmVyaWVzfSBzdGFrZXMgZGVhZGxvY2stZnJlZWRvbSBvbiBpdCwgc28gdGhlXG4gKiBjb25kaXRpb24gbGl2ZXMgaGVyZSByYXRoZXIgdGhhbiBiZWluZyBzcGVsbGVkIG91dCB0d2ljZS5cbiAqXG4gKiBPbmUgZGVsaWJlcmF0ZSBleGNlcHRpb246IHRoZSBsb2ctb3JkZXItZHJhd3MgdHVybnN0aWxlIGluXG4gKiB7QGxpbmsgcXVpZXNjZUVhcmxpZXJDYXNjYWRlc30gd2FpdHMgb24gQU5ZIGxvd2VyIGFybWVkIGVudHJ5LCBhIHN0cmljdGx5XG4gKiB3aWRlciByZWxhdGlvbiB0aGFuIHRoaXMgb25lLiBXaHkgdGhhdCB3aWR0aCBjYW5ub3QgZGVhZGxvY2sgdGhlXG4gKiBzYWZldHktbmV0IGRpc3BlbnNlciBpcyBhcmd1ZWQgYXQgdGhlIHR1cm5zdGlsZSBpdHNlbGYuXG4gKi9cbmZ1bmN0aW9uIGdhdGVzT24oXG4gIGtpbmQ6IERlbGl2ZXJ5S2luZCxcbiAgaW5kZXg6IG51bWJlcixcbiAgb3RoZXJJbmRleDogbnVtYmVyLFxuICBvdGhlcjogRGVsaXZlcnlCYXJyaWVyRW50cnlcbik6IGJvb2xlYW4ge1xuICBpZiAob3RoZXJJbmRleCA+PSBpbmRleCB8fCAhREVGRVJfQkVISU5EW2tpbmRdLmluY2x1ZGVzKG90aGVyLmtpbmQpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIC8vIEEgc3RlcCBza2lwcyBhbiBVTkFSTUVEIGVhcmxpZXIgZW50cnkgKGFuIHVuY2xhaW1lZCBidWZmZXJlZCBob29rXG4gIC8vIHBheWxvYWQpLiBTZWUgdGhlIGFzeW1tZXRyeSBkZXNjcmliZWQgb24gYGF3YWl0RWFybGllckRlbGl2ZXJpZXNgLiBUaGVcbiAgLy8gc2tpcCBpcyBkaXJlY3QsIG5ldmVyIHRyYW5zaXRpdmU6IGFybWVkIGVudHJpZXMgYXJlIHN0aWxsIGdhdGVkIG9uLCBldmVuXG4gIC8vIHdoZW4gdGhleSBhcmUgdGhlbXNlbHZlcyBwYXJrZWQgYmVoaW5kIHN1Y2ggYSBwYXlsb2FkLlxuICByZXR1cm4gIShraW5kID09PSAnc3RlcCcgJiYgIW90aGVyLmFybWVkKTtcbn1cblxuLyoqXG4gKiBXaGV0aGVyIGBlbnRyeWAgd2lsbCByZXNvbHZlIG9uIGl0cyBvd246IGl0IGlzIGFybWVkLCBhbmQgZXZlcnkgZWFybGllclxuICogZGVsaXZlcnkgaXQgYWN0dWFsbHkgZ2F0ZXMgb24gKHtAbGluayBnYXRlc09ufSkgd2lsbCBsaWtld2lzZSByZXNvbHZlIG9uIGl0c1xuICogb3duLlxuICpcbiAqIEEgc3RlcCBkb2VzIG5vdCBnYXRlIG9uIGFuIHVuY2xhaW1lZCBidWZmZXJlZCBwYXlsb2FkLCBzbyBzdWNoIGEgcGF5bG9hZFxuICogY2Fubm90IGtlZXAgaXQgZnJvbSByZXNvbHZpbmcuIEEgc3RlcCBET0VTIGdhdGUgb24gZWFybGllciBhcm1lZCB3YWl0cyBhbmRcbiAqIGhvb2tzLCBzbyBvbmUgcGFya2VkIGJlaGluZCBhbiB1bmNsYWltZWQgcGF5bG9hZCBtYWtlcyB0aGUgc3RlcFxuICogbm9uLXNlbGYtcmVzb2x2aW5nIGluIHR1cm4uIERpc2FncmVlaW5nIHdpdGgge0BsaW5rIGF3YWl0RWFybGllckRlbGl2ZXJpZXN9XG4gKiBoZXJlIHdvdWxkIG5vdCBiZSBhIGNvc21ldGljIHByb2JsZW06IHRoaXMgcHJlZGljYXRlIGlzIHdoYXRcbiAqIHtAbGluayBoYXNQYXJrZWRDb21taXR0ZWREZWxpdmVyeX0gdXNlcyB0byBkZWNpZGUgd2hldGhlciBpZGxlIGlzIHJlYWNoYWJsZSxcbiAqIGFuZCBhbiBlbnRyeSByZXBvcnRlZCBzZWxmLXJlc29sdmluZyB3aGlsZSBpdCBpcyBpbiBmYWN0IHBhcmtlZCBiZWhpbmQgYVxuICogcGF5bG9hZCB0aGF0IG9ubHkgdGhlIGlkbGUgc2FmZXR5IG5ldCBjYW4gcmV0aXJlIHdvdWxkIGdhdGUgaXRzIG93blxuICogcmV0aXJlbWVudC5cbiAqXG4gKiBSZWN1cnNpb24gdGVybWluYXRlcyBiZWNhdXNlIGV2ZXJ5IGVkZ2UgcG9pbnRzIHRvIGEgc3RyaWN0bHkgc21hbGxlciBpbmRleC5cbiAqIGBtZW1vYCBrZWVwcyB0aGUgd2FsayBsaW5lYXIgaW4gcmVnaXN0cnkgc2l6ZSwgYW5kIHRoZSByZWdpc3RyeSBpcyBub3Qgc21hbGxcbiAqIGJ5IGNvbnN0cnVjdGlvbjogYEV2ZW50c0NvbnN1bWVyYCBkcmFpbnMgY29uc2VjdXRpdmVseSBjb25zdW1hYmxlIGV2ZW50c1xuICogc3luY2hyb25vdXNseSB3aGlsZSBiYXJyaWVycyBvbmx5IHJldGlyZSBvbiBtaWNyb3Rhc2stZHJpdmVuIGRlbGl2ZXJpZXMsIHNvXG4gKiBhIGZhbi1vdXQgb2YgYFByb21pc2UucmFjZShbaG9vaywgc2xlZXBdKWAgYnJhbmNoZXMgYWNjdW11bGF0ZXMgb25lIGJhcnJpZXJcbiAqIHBlciBicmFuY2ggcGVyIGtpbmQuIFRoZSBtZW1vIE1VU1QgYmUgcGVyLWNhbGw6IGBhcm1lZGAgbXV0YXRlcyBiZXR3ZWVuXG4gKiBjYWxscyBhcyBidWZmZXJlZCBwYXlsb2FkcyBhcmUgY2xhaW1lZC5cbiAqXG4gKiBUaGUgbWVtbyBpcyBhbiBvcHRpbWl6YXRpb24sIG5vdCBhIGNvcnJlY3RuZXNzIHJlcXVpcmVtZW50LiBJdCBvbmNlIHdhcyBvbmU6XG4gKiBgYXdhaXRFYXJsaWVyRGVsaXZlcmllc2AgdXNlZCB0byBydW4gdGhpcyB3YWxrIGZvciBldmVyeSBlYXJsaWVyIGVudHJ5IG9mIGFcbiAqIHN0ZXAgZGVsaXZlcnksIHdpdGggbm8gZWFybHkgZXhpdCwgd2hpY2ggdW5tZW1vaXplZCBpcyBUKG4pID0gzqMgVChqKSxcbiAqIG1lYXN1cmVkIGF0IDQuM2U4IHJlY3Vyc2l2ZSBjYWxscyAoODRzKSBmb3IgNDAgYWx0ZXJuYXRpbmcgYXJtZWQgaG9vay93YWl0XG4gKiBiYXJyaWVycy4gVGhhdCBjYWxsIHNpdGUgaXMgZ29uZTsgYSBzdGVwIG5vdyB0ZXN0cyBgYXJtZWRgIGRpcmVjdGx5LiBUaGUgb25lXG4gKiBzdXJ2aXZpbmcgY2FsbGVyLCB7QGxpbmsgaGFzUGFya2VkQ29tbWl0dGVkRGVsaXZlcnl9LCBjYW5ub3QgcmVhY2ggdGhhdFxuICogc2hhcGU6IGl0IHJldHVybnMgYXQgdGhlIEZJUlNUIHNlbGYtcmVzb2x2aW5nIGVudHJ5LCBzbyBpdCBvbmx5IGV2ZXJcbiAqIGFkdmFuY2VzIHBhc3QgZW50cmllcyB0aGF0IGFyZSBub24tc2VsZi1yZXNvbHZpbmcsIGFuZCB0aG9zZSBzaG9ydC1jaXJjdWl0XG4gKiBvbiB0aGVpciBmaXJzdCBmYWxzZSBjaGlsZC4gRXZlcnkgZW50cnkgaXQgZXZhbHVhdGVzIHRoZXJlZm9yZSBoYXNcbiAqIGFsbC1mYWxzZSBwcmVkZWNlc3NvcnMgYW5kIHJldHVybnMgYWZ0ZXIgb25lIGNoaWxkLCBkZWdlbmVyYXRpbmcgdGhlIHdhbGsgdG9cbiAqIGEgY2hhaW4gKG1lYXN1cmVkOiA5OCBjYWxscyB1bm1lbW9pemVkIGZvciB0aGUgd29yc3QgNDAtYmFycmllciBzaGFwZSwgMVxuICogY2FsbCBmb3IgdGhlIHJlZ2lzdHJ5IGFib3ZlKS4gRG8gbm90IHJlc3RvcmUgYW4gZXhwb25lbnRpYWwgY2xhaW0gaGVyZVxuICogd2l0aG91dCByZXN0b3JpbmcgYSBjYWxsZXIgdGhhdCBjYW4gcHJvZHVjZSBpdC5cbiAqL1xuZnVuY3Rpb24gcmVzb2x2ZXNPbkl0c093bihcbiAgYmFycmllcnM6IE1hcDxudW1iZXIsIERlbGl2ZXJ5QmFycmllckVudHJ5PixcbiAgaW5kZXg6IG51bWJlcixcbiAgZW50cnk6IERlbGl2ZXJ5QmFycmllckVudHJ5LFxuICBtZW1vOiBNYXA8bnVtYmVyLCBib29sZWFuPlxuKTogYm9vbGVhbiB7XG4gIGNvbnN0IGNhY2hlZCA9IG1lbW8uZ2V0KGluZGV4KTtcbiAgaWYgKGNhY2hlZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIGNhY2hlZDtcbiAgfVxuICBjb25zdCByZXN1bHQgPSBjb21wdXRlUmVzb2x2ZXNPbkl0c093bihiYXJyaWVycywgaW5kZXgsIGVudHJ5LCBtZW1vKTtcbiAgbWVtby5zZXQoaW5kZXgsIHJlc3VsdCk7XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmZ1bmN0aW9uIGNvbXB1dGVSZXNvbHZlc09uSXRzT3duKFxuICBiYXJyaWVyczogTWFwPG51bWJlciwgRGVsaXZlcnlCYXJyaWVyRW50cnk+LFxuICBpbmRleDogbnVtYmVyLFxuICBlbnRyeTogRGVsaXZlcnlCYXJyaWVyRW50cnksXG4gIG1lbW86IE1hcDxudW1iZXIsIGJvb2xlYW4+XG4pOiBib29sZWFuIHtcbiAgaWYgKCFlbnRyeS5hcm1lZCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBmb3IgKGNvbnN0IFtvdGhlckluZGV4LCBvdGhlcl0gb2YgYmFycmllcnMpIHtcbiAgICBpZiAoIWdhdGVzT24oZW50cnkua2luZCwgaW5kZXgsIG90aGVySW5kZXgsIG90aGVyKSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGlmICghcmVzb2x2ZXNPbkl0c093bihiYXJyaWVycywgb3RoZXJJbmRleCwgb3RoZXIsIG1lbW8pKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG4gIHJldHVybiB0cnVlO1xufVxuXG4vKipcbiAqIEF3YWl0cywgaW4gc3RyaWN0IGV2ZW50LWxvZyBvcmRlciwgZXZlcnkgc3RpbGwtcmVnaXN0ZXJlZCBkZWxpdmVyeSB0aGF0IGlzXG4gKiBlYXJsaWVyIGluIHRoZSBsb2cgdGhhbiBgZXZlbnRJbmRleGAgYW5kIHRoYXQgYSBkZWxpdmVyeSBvZiBga2luZGAgZGVmZXJzXG4gKiBiZWhpbmQgKHNlZSB7QGxpbmsgREVGRVJfQkVISU5EfSksIHNvIHRoYXQgdGhpcyByZXNvbHV0aW9uIGlzIGhhbmRlZCB0byB0aGVcbiAqIHdvcmtmbG93IG9ubHkgYWZ0ZXIgYWxsIHJlbGV2YW50IGVhcmxpZXItaW4tbG9nIGRlbGl2ZXJpZXMgaGF2ZSBiZWVuLiBUaGlzXG4gKiBpcyB3aGF0IGtlZXBzIGEgYFByb21pc2UucmFjZWAgKG9yIHRoZSBVTElEIGEgZm9sbG93LXVwIGB1c2VTdGVwYCBkcmF3cyBvblxuICogYSBjb25jdXJyZW50IGJyYW5jaCkgZGV0ZXJtaW5pc3RpYyBhbmQgYWxpZ25lZCB3aXRoIHRoZSBjb21taXR0ZWQgZXZlbnRcbiAqIGxvZywgaW5kZXBlbmRlbnQgb2YgbWljcm90YXNrLWhvcCBjb3VudHMsIGh5ZHJhdGlvbiB0aW1lLCBvciByYWNlLWFyZ3VtZW50XG4gKiBvcmRlci4gV2hlbiB0aGlzIGRlbGl2ZXJ5IGRvZXMgaGF2ZSB0byB3YWl0LCBpdCBhbHNvIHlpZWxkcyBhIG1hY3JvdGFza1xuICogYWZ0ZXJ3YXJkcyBzbyB0aGUgZWFybGllciBkZWxpdmVyeSdzIGNvbnN1bWVyIGNhbiBydW4gdG8gaXRzIG93biBuZXh0XG4gKiBzdXNwZW5zaW9uIHBvaW50IGZpcnN0OyBzZWUgdGhlIGNvbW1lbnQgYXQgdGhhdCBgYXdhaXRgIGZvciB3aHkgb3JkZXJpbmcgdGhlXG4gKiBgcmVzb2x2ZSgpYCBjYWxscyBhbG9uZSBpcyBub3QgZW5vdWdoLlxuICpcbiAqIFdoYXQgY291bnRzIGFzIFwiZGVmZXJzIGJlaGluZFwiIGlzIHtAbGluayBnYXRlc09ufSwgc2hhcmVkIHdpdGhcbiAqIHtAbGluayBjb21wdXRlUmVzb2x2ZXNPbkl0c093bn0gc28gdGhlIHR3byBjYW5ub3QgZHJpZnQuXG4gKlxuICogT25lIGFzeW1tZXRyeTogYSBTVEVQIHJlc3VsdCBza2lwcyBhbnkgZWFybGllciBkZWxpdmVyeSB0aGF0IGlzIFVOQVJNRUQsXG4gKiBpLmUuIGEgYnVmZmVyZWQgaG9vayBwYXlsb2FkIG5vIGNvbnN1bWVyIGhhcyBjbGFpbWVkLiBTdWNoIGEgcGF5bG9hZCBpc1xuICogZGVsaXZlcmVkIG9ubHkgd2hlbiB0aGUgd29ya2Zsb3cgbmV4dCByZWFkcyB0aGUgaG9vaywgYW5kIHJlYWNoaW5nIHRoYXQgcmVhZFxuICogb2Z0ZW4gcmVxdWlyZXMgdGhlIHN0ZXAgcmVzdWx0IGl0c2VsZiAoYGF3YWl0IHN0ZXBYKClgIGJlZm9yZSB0aGVcbiAqIHJlYWQpLiBHYXRpbmcgdGhlIHN0ZXAgb24gaXQgd291bGQgc3RhbGwgdGhlIHdvcmtmbG93IHVudGlsIHRoZSBiYXJyaWVyJ3NcbiAqIGlkbGUgc2FmZXR5IG5ldCBmaXJlcywgd2hpY2ggdGhlbiByZWxlYXNlcyBldmVyeSBkZWxpdmVyeSBxdWV1ZWQgYmVoaW5kIHRoYXRcbiAqIHBheWxvYWQgYXQgb25jZSwgbG9zaW5nIGV4YWN0bHkgdGhlIHJhY2UgdGhpcyBvcmRlcmluZyBleGlzdHMgdG8gcHJvdGVjdC5cbiAqIFdhaXRzIGFuZCBob29rcyBrZWVwIGdhdGluZyBvbiB1bmNsYWltZWQgcGF5bG9hZHM6IGZvciB0aGVtLCB3YWl0aW5nIGZvciB0aGVcbiAqIGNsYWltIElTIHRoZSBvcmRlcmluZyBndWFyYW50ZWUgKGEgYHdhaXRfY29tcGxldGVkYCBtdXN0IG5vdCBwcmVlbXB0IGFcbiAqIHBheWxvYWQgdGhlIGxvZyBvcmRlcmVkIGZpcnN0KS5cbiAqXG4gKiBUaGUgc2tpcCBpcyBkaXJlY3QsIG5ldmVyIHRyYW5zaXRpdmUuIEEgc3RlcCBzdGlsbCBnYXRlcyBvbiBhbiBlYXJsaWVyIEFSTUVEXG4gKiB3YWl0IG9yIGhvb2ssIGluY2x1ZGluZyBvbmUgdGhhdCBpcyBpdHNlbGYgcGFya2VkIGJlaGluZCBhbiB1bmNsYWltZWRcbiAqIHBheWxvYWQuIFNraXBwaW5nIHRob3NlIHRvbyB3b3VsZCBpbnZlcnQgbG9nIG9yZGVyIGZvciB0aGUgY29tbW9uZXN0IHNoYXBlXG4gKiB0aGVyZSBpczogYSB3b3JrZmxvdyB0aGF0IGNyZWF0ZXMgYSBob29rIGl0IGRvZXMgbm90IHJlYWQgb24gdGhpcyBicmFuY2gsXG4gKiByYWNlcyBgc3RlcGAgYWdhaW5zdCBgc2xlZXBgLCBhbmQgaGFzIHRoZSBsb2cgc2F5IHRoZSBzbGVlcCB3b24uIFRoZSBzdGVwXG4gKiB3b3VsZCB0aGVuIG92ZXJ0YWtlIHRoZSB3YWl0LCBib3RoIGJyYW5jaGVzIHdvdWxkIHN3YXAgdGhlIGNvcnJlbGF0aW9uIGlkc1xuICogdGhleSBkcmF3IG5leHQsIGFuZCByZXBsYXkgd291bGQgZGl2ZXJnZS4gU2VlXG4gKiBgc3RlcC1kZWxpdmVyeS1vcmRlcmluZy50ZXN0LnRzYC4gV2FpdGluZyBpbnN0ZWFkIGlzIHNhZmUgYmVjYXVzZSB0aGVcbiAqIHBheWxvYWQncyBvd24gaWRsZSBzYWZldHkgbmV0IHJldGlyZXMgaXQgYW5kIHRoZSB3aG9sZSBjaGFpbiB0aGVuIGRlbGl2ZXJzXG4gKiBpbiBsb2cgb3JkZXI7IHtAbGluayBoYXNQYXJrZWRDb21taXR0ZWREZWxpdmVyeX0gZGVsaWJlcmF0ZWx5IHJlcG9ydHMgc3VjaCBhXG4gKiBzdGVwIGFzIG5vdCBzZWxmLXJlc29sdmluZyBzbyB0aGF0IGlkbGUgc3RheXMgcmVhY2hhYmxlLlxuICpcbiAqIFwiVGhlIHdob2xlIGNoYWluIHRoZW4gZGVsaXZlcnMgaW4gbG9nIG9yZGVyXCIgcmVzdHMgb24gdGhlIFBBWUxPQUQncyBiYXJyaWVyXG4gKiBiZWluZyByZXRpcmVkIGJlZm9yZSB0aGF0IG9mIGFueXRoaW5nIHBhcmtlZCBiZWhpbmQgaXQuIFRoYXQgb3JkZXIgaXNcbiAqIHN0cnVjdHVyYWw6IHNhZmV0eS1uZXQgcmV0aXJlbWVudHMgZ28gdGhyb3VnaCBvbmUgcGVyLWNvbnRleHQgZGlzcGVuc2VyIHRoYXRcbiAqIG9ubHkgZXZlciByZXRpcmVzIHRoZSBsb3dlc3QtaW5kZXggZW50cnkgYXQgZGVsaXZlcnkgaWRsZSwgYW5kIGV2ZXJ5XG4gKiByZXRpcmVtZW50IHRoYXQgd2FrZXMgYSBjaGFpbiBmbGlwcyB7QGxpbmsgaGFzUGFya2VkQ29tbWl0dGVkRGVsaXZlcnl9IGJhY2tcbiAqIHRvIHRydWUsIHJlLWJsb2NraW5nIHRoZSBkaXNwZW5zZXIgdW50aWwgdGhlIGNoYWluIGhhcyBkcmFpbmVkLiBTZWVcbiAqIHtAbGluayBlbnN1cmVCYXJyaWVyU2FmZXR5TmV0fS4gKFRoaXMgdXNlZCB0byByZXN0IG9uIHRoZSBGSUZPIG9mIG9uZSBpZGxlXG4gKiBwb2xsIHBlciBiYXJyaWVyLCB3aGljaCBoZWxkIGZvciBhIHNpbmdsZSBwYXJrZWQgc2VnbWVudCBidXQgZGVjYXllZCB0b1xuICogdGltaW5nIG5vaXNlIHdpdGggc2V2ZXJhbDogdGhlIHJlbGVhc2Ugb3JkZXIsIGFuZCB0aGVyZWZvcmUgdGhlIFVMSURzXG4gKiBkcmF3biBieSB0aGUgd29rZW4gYnJhbmNoZXMsIHRoZW4gZGVwZW5kZWQgb24gaG93IG11Y2ggbG9nIHRoZSByZXBsYXkgaGFkXG4gKiBsb2FkZWQuIHN0b3JtLWxvZy1yZXBsYXkudGVzdC50cyByZXBsYXlzIGEgcHJvZHVjdGlvbiBsb2cgY29ycnVwdGVkIGV4YWN0bHlcbiAqIHRoYXQgd2F5LilcbiAqL1xuLyoqXG4gKiBXaGV0aGVyIGNvcnJlbGF0aW9uLWlkIGRyYXcgb3JkZXIgaXMgcGlubmVkIHRvIGV2ZW50LWxvZyBvcmRlci4gRGVmYXVsdCBPTjpcbiAqIG9ubHkgdGhlIGxpdGVyYWwgc3RyaW5nIGBXT1JLRkxPV19MT0dfT1JERVJfRFJBV1M9MGAgb3B0cyBvdXQuIGA9ZmFsc2VgLFxuICogYD1vZmZgLCBhbmQgZXZlcnkgb3RoZXIgdmFsdWUga2VlcCBpdCBlbmFibGVkLiBSZWFkIHBlciBjYWxsIHNvIHRlc3RzIGNhblxuICogZmxpcCBpdC5cbiAqXG4gKiBPZmYsIGEgZGVsaXZlcnkgdGhhdCBoYWQgdG8gZGVmZXIgeWllbGRzIE9ORSBtYWNyb3Rhc2sgYWZ0ZXIgaXRzXG4gKiBwcmVkZWNlc3NvcnMgcmVzb2x2ZS4gVGhpcyBpcyBlbm91Z2ggZm9yIHNob3J0IGNvbnN1bWVycywgYnV0IGEgd29rZW4gYnJhbmNoXG4gKiB3aG9zZSBwYXRoIHRvIGl0cyBuZXh0IGRyYXcgY3Jvc3NlcyBtb3JlIGhvcHMgKGEgYFByb21pc2UucmFjZWAgcmVzb2x1dGlvbiwgYVxuICogdXNlci1sZXZlbCBzZW1hcGhvcmUsIGFuIGFzeW5jLWl0ZXJhdG9yIHJlYWQpIGNhbiBzdGlsbCBiZSBvdmVydGFrZW4gYnkgYVxuICogbGF0ZXItaW4tbG9nIGRlbGl2ZXJ5J3Mgc2hvcnRlciBjYXNjYWRlLCBzbyB0aGUgcnVuJ3MgZHJhdyBvcmRlciwgaW5jbHVkaW5nXG4gKiBpdHMgY29ycmVsYXRpb24gaWRzLCBkZXBlbmRzIG9uIGhvdyBtdWNoIGxvZyB0aGlzIHJlcGxheSBsb2FkZWQuXG4gKiBPbiwgdGhlIHlpZWxkIGJlY29tZXMgYSBmaXhwb2ludDogdGhlIGRlbGl2ZXJ5IHJlc29sdmVzIG9ubHkgb25jZSBldmVyeVxuICogZWFybGllciBjYXNjYWRlIGhhcyBxdWllc2NlZCwgbWFraW5nIHRoZSBkcmF3IHNlcXVlbmNlIGEgcHVyZSBmdW5jdGlvbiBvZlxuICogdGhlIGRlbnNlIGxvZywgc3RhYmxlIHVuZGVyIHByZWZpeCBleHRlbnNpb24sIGFuZCBjb25jdXJyZW50IHdyaXRlcnMnXG4gKiBkdXBsaWNhdGUgY3JlYXRlcyBpZGVudGljYWwgKGRlZHVwZWQpIGluc3RlYWQgb2YgY29sbGlkaW5nLlxuICovXG5mdW5jdGlvbiBpc0xvZ09yZGVyRHJhd3NFbmFibGVkKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gcHJvY2Vzcy5lbnYuV09SS0ZMT1dfTE9HX09SREVSX0RSQVdTICE9PSAnMCc7XG59XG5cbi8qKlxuICogT25lIHF1aWVzY2VuY2UgdHVybjogbGV0cyB0aGUgZW50aXJlIHBlbmRpbmcgbWljcm90YXNrIHF1ZXVlIGRyYWluLCB0aGVuXG4gKiB5aWVsZHMgdG8gdGhlIGV2ZW50IGxvb3Agb25jZS4gYHNldEltbWVkaWF0ZWAgKGNoZWNrIHBoYXNlKSBpcyB1c2VkIHdoZXJlXG4gKiBhdmFpbGFibGUgYmVjYXVzZSBOb2RlIGNsYW1wcyBgc2V0VGltZW91dCgwKWAgdG8gfjFtcyB3aGlsZSBgc2V0SW1tZWRpYXRlYFxuICogY29zdHMgfjIwwrVzLiBFdmVyeSBicmFuY2gtZGVjaWRpbmcgZGVsaXZlcnkgcGF5cyB0aGlzIHR1cm4gYXQgbGVhc3RcbiAqIG9uY2UsIHNvIG9uIGEgc2VxdWVudGlhbCByZXBsYXkgdGhlIGNsYW1wIGlzIHRoZSB3aG9sZSBjb3N0LiBUaW1lcnMgc3RpbGxcbiAqIHJ1biBiZXR3ZWVuIGNvbnNlY3V0aXZlIHR1cm5zICh0aGUgbG9vcCByZS1lbnRlcnMgdGhlIGV2ZW50IGxvb3AgZWFjaFxuICogaXRlcmF0aW9uLCBwYXNzaW5nIHRocm91Z2ggdGhlIHRpbWVycyBwaGFzZSksIHNvIGNoYWlucyBwYXJrZWQgb24gdGhlXG4gKiBzYWZldHktbmV0IGRpc3BlbnNlcidzIGBzZXRUaW1lb3V0YCBjYWRlbmNlIGFyZSBub3Qgc3RhcnZlZC5cbiAqL1xuZnVuY3Rpb24gcXVpZXNjZW5jZVR1cm4oZGVsYXlNczogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gIGlmIChkZWxheU1zID09PSAwICYmIHR5cGVvZiBzZXRJbW1lZGlhdGUgPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUpID0+IHNldEltbWVkaWF0ZShyZXNvbHZlKSk7XG4gIH1cbiAgcmV0dXJuIG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIGRlbGF5TXMpKTtcbn1cblxuLyoqXG4gKiBXYWl0cyB1bnRpbCB0aGUgd29ya2Zsb3cgY2FuIG1ha2Ugbm8gZnVydGhlciBwcm9ncmVzcyB3aXRob3V0IGFub3RoZXJcbiAqIGRlbGl2ZXJ5OiByZXBlYXRlZCAocHJvbWlzZS1xdWV1ZSBkcmFpbiArIGV2ZW50LWxvb3AgdHVybilzIHVudGlsIGEgZnVsbFxuICogdHVybiBwYXNzZXMgd2l0aCBubyBuZXcgVUxJRCBkcmF3cyBhbmQgbm8gaHlkcmF0aW9uIGluIGZsaWdodC5cbiAqXG4gKiBUZXJtaW5hdGlvbjogZWFjaCBleHRyYSBpdGVyYXRpb24gcmVxdWlyZXMgYSBuZXcgVUxJRCBkcmF3IG9yIGEgaHlkcmF0aW9uXG4gKiBzdGFydGVkIGluIHRoZSBwcmV2aW91cyB0dXJuLiBgbWludENvdW50YCBjb3VudHMgRVZFUlkgZHJhdyBmcm9tIHRoZSBydW4nc1xuICogc2VxdWVuY2UsIGluY2x1ZGluZyBjb3JyZWxhdGlvbiBpZHMgYW5kIHNlcmlhbGl6YXRpb24tZHJpdmVuIGRyYXdzIChzdHJlYW1cbiAqIGlkcyBtaW50ZWQgdGhyb3VnaCB0aGUgYFNUQUJMRV9VTElEYCBnbG9iYWwgd2hpbGUgZGVoeWRyYXRpbmcpLiBUaGlzIGlzXG4gKiBjb25zZXJ2YXRpdmUgaW4gdGhlIHNhZmUgZGlyZWN0aW9uOiBzZXJpYWxpemF0aW9uIGRyYXdzIG9ubHkgZXh0ZW5kIHRoZVxuICogd2FpdCwgYW5kIGJvdGggYm9keSBwcm9ncmVzcyBhbmQgdGhlIHNlcmlhbGl6YXRpb24gd29yayBvbmUgY2FzY2FkZSBjYW5cbiAqIHNjaGVkdWxlIGFyZSBmaW5pdGUgYmV0d2VlbiBkZWxpdmVyaWVzLCBzbyB0aGUgZml4cG9pbnQgaXMgcmVhY2hlZC4gVGhlXG4gKiBsb29wIGhvbGRzIHRoaXMgZGVsaXZlcnkncyBvd24gYmFycmllciByZWdpc3RlcmVkIChpdHMgYG1hcmtEZWxpdmVyZWRgIGhhc1xuICogbm90IHJ1biksIHNvIGBpc0RlbGl2ZXJ5SWRsZWAgc3RheXMgZmFsc2UgYW5kIG5vIHN1c3BlbnNpb24gY2FuIHByZWVtcHQgdGhlXG4gKiBjYXNjYWRlIGJlaW5nIHdhaXRlZCBvdXQuXG4gKlxuICogQSByZWplY3RlZCBgcHJvbWlzZVF1ZXVlYCBzZXR0bGVzIGltbWVkaWF0ZWx5IGFuZCBmb3JldmVyLCBzbyBsb29waW5nIGF0XG4gKiB0aGUgbm9ybWFsIGNhZGVuY2Ugb24gYSBmYWlsZWQgcnVuIHdvdWxkIGRlZ2VuZXJhdGUgaW50byBhIGJ1c3kgbG9vcCAodGhlXG4gKiBzYW1lIGhhemFyZCB7QGxpbmsgZW5zdXJlQmFycmllclNhZmV0eU5ldH0gZG9jdW1lbnRzKS4gSXRlcmF0aW9ucyB0aGF0XG4gKiBvYnNlcnZlIHRoZSBxdWV1ZSByZWplY3RlZCBiYWNrIG9mZiB0byBhIDUwbXMgdGljayBpbnN0ZWFkLlxuICovXG5hc3luYyBmdW5jdGlvbiBxdWllc2NlRWFybGllckNhc2NhZGVzKFxuICBjdHg6IFdvcmtmbG93T3JjaGVzdHJhdG9yQ29udGV4dCxcbiAgZXZlbnRJbmRleDogbnVtYmVyXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgZm9yICg7Oykge1xuICAgIGNvbnN0IG1pbnRzQmVmb3JlID0gY3R4Lm1pbnRDb3VudCA/PyAwO1xuICAgIGNvbnN0IHBlbmRpbmdCZWZvcmUgPSBjdHgucGVuZGluZ0RlbGl2ZXJpZXM7XG4gICAgLy8gU2V0dGxlZCBvciByZWplY3RlZCwgdGhlIHF1ZXVlIHNuYXBzaG90IG9ubHkgb3JkZXJzIHVzIGJlaGluZCB3b3JrXG4gICAgLy8gYWxyZWFkeSBjaGFpbmVkOyBhIHJlamVjdGlvbiBpcyB0aGUgcnVuIGZhaWxpbmcgZWxzZXdoZXJlLlxuICAgIGNvbnN0IHF1ZXVlUmVqZWN0ZWQgPSBhd2FpdCBjdHgucHJvbWlzZVF1ZXVlLnRoZW4oXG4gICAgICAoKSA9PiBmYWxzZSxcbiAgICAgICgpID0+IHRydWVcbiAgICApO1xuICAgIGF3YWl0IHF1aWVzY2VuY2VUdXJuKHF1ZXVlUmVqZWN0ZWQgPyA1MCA6IDApO1xuICAgIGlmIChcbiAgICAgIChjdHgubWludENvdW50ID8/IDApICE9PSBtaW50c0JlZm9yZSB8fFxuICAgICAgcGVuZGluZ0JlZm9yZSAhPT0gMCB8fFxuICAgICAgY3R4LnBlbmRpbmdEZWxpdmVyaWVzICE9PSAwXG4gICAgKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgLy8gUXVpZXQgaXMgbm90IGVub3VnaCBvbiBpdHMgb3duOiBzZXZlcmFsIGRlbGl2ZXJ5IGNoYWlucyBjYW4gYmUgc2l0dGluZ1xuICAgIC8vIGluIHRoaXMgbG9vcCBhdCBvbmNlLCBhbmQgbGV0dGluZyB0aGUgZmlyc3QgcXVpZXQgb2JzZXJ2YXRpb24gcmVzb2x2ZVxuICAgIC8vIHdvdWxkIGJyZWFrIHRoZSB0aWUgYnkgdGltZXIgYXJyaXZhbC4gVGhpcyBtb2RlIHJlbW92ZXMgdGhhdCBhcnJpdmFsLW9yZGVyXG4gICAgLy8gZGVwZW5kZW5jZS4gQSBsb3dlci1pbmRleCBBUk1FRCBiYXJyaWVyIGlzIGEgZGVsaXZlcnkgY29tbWl0dGVkIHRvXG4gICAgLy8gaGFwcGVuaW5nIHRoYXQgaGFzIG5vdCBoYXBwZW5lZCB5ZXQsIHNvIHRoaXMgb25lIGtlZXBzIHdhaXRpbmcuIFVuYXJtZWRcbiAgICAvLyBlbnRyaWVzIChidWZmZXJlZCBwYXlsb2FkcyBub2JvZHkgaGFzIGNsYWltZWQpIGRvIG5vdCBibG9jaywgZXhhY3RseSBhc1xuICAgIC8vIGluIGBnYXRlc09uYDogdGhlaXIgaGFuZG92ZXIgaXMgY2xhaW0tZHJpdmVuLCB3aGljaCBpcyBib2R5LXBvc2l0aW9uXG4gICAgLy8gZGV0ZXJtaW5lZCBhbmQgdGhlcmVmb3JlIGFscmVhZHkgYSBmdW5jdGlvbiBvZiB0aGUgcHJlZml4LlxuICAgIC8vXG4gICAgLy8gVGhpcyBpcyBkZWxpYmVyYXRlbHkgYSBXSURFUiB3YWl0cy1mb3IgcmVsYXRpb24gdGhhbiBgZ2F0ZXNPbmAgKHdoaWNoLFxuICAgIC8vIGUuZy4sIGV4Y2x1ZGVzIHdhaXTihpJ3YWl0KTogdW5kZXIgbG9nLW9yZGVyIGRyYXdzIEVWRVJZIGJyYW5jaC1kZWNpZGluZ1xuICAgIC8vIGRlbGl2ZXJ5IG11c3QgcmVzb2x2ZSBpbiBsb2cgb3JkZXIsIGtpbmRzIGluY2x1ZGVkLiBUaGUgd2lkdGggaXMgc2FmZVxuICAgIC8vIGFnYWluc3QgdGhlIGRpc3BlbnNlciBkZWFkbG9jayB0aGF0IGByZXNvbHZlc09uSXRzT3duYCBndWFyZHMsIGJlY2F1c2VcbiAgICAvLyB0aGUgb25lIGVkZ2UgdGhlIHdpZGVyIHJlbGF0aW9uIGFkZHMgKHdhaXRpbmcgb24gYW4gYXJtZWQgZW50cnkgdGhhdFxuICAgIC8vIGdhdGVzT24gZG9lcyBub3QgbW9kZWwpIGFsd2F5cyBib3R0b21zIG91dCBhdCB0aGUgc2FtZSB1bmFybWVkIHBheWxvYWQ6XG4gICAgLy8gYSBsb3dlciBhcm1lZCBXQUlUIGlzIG5vbi1zZWxmLXJlc29sdmluZyBvbmx5IHdoZW4gaXQgaXMgKHRyYW5zaXRpdmVseSlcbiAgICAvLyBwYXJrZWQgYmVoaW5kIGFuIHVuY2xhaW1lZCBidWZmZXJlZCBwYXlsb2FkLCBhbmQgYSB3YWl0IGdhdGVzIG9uIGV2ZXJ5XG4gICAgLy8gbG93ZXIgaG9vayBhbmQgc3RlcCBkaXJlY3RseSwgc28gdGhlIHNwaW5uZXIgaGVyZSBhbHNvIGdhdGVzIG9uIHRoYXRcbiAgICAvLyBwYXlsb2FkIHRocm91Z2ggYGdhdGVzT25gIGFuZCBpcyBpdHNlbGYgcmVwb3J0ZWQgbm9uLXNlbGYtcmVzb2x2aW5nLlxuICAgIC8vIFRoZSBkaXNwZW5zZXIgdGhlcmVmb3JlIHN0YXlzIHVuYmxvY2tlZCBhbmQgcmV0aXJlcyB0aGUgY2hhaW4gaGVhZDsgc2VlXG4gICAgLy8gdGhlIHBhcmtlZC1jaGFpbiB0ZXN0IGluIGRlbGl2ZXJ5LWJhcnJpZXItY292ZXJhZ2UudGVzdC50cy5cbiAgICBsZXQgbG93ZXJBcm1lZCA9IGZhbHNlO1xuICAgIGZvciAoY29uc3QgW2luZGV4LCBlbnRyeV0gb2YgY3R4LnBlbmRpbmdEZWxpdmVyeUJhcnJpZXJzID8/IFtdKSB7XG4gICAgICBpZiAoaW5kZXggPCBldmVudEluZGV4ICYmIGVudHJ5LmFybWVkKSB7XG4gICAgICAgIGxvd2VyQXJtZWQgPSB0cnVlO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKCFsb3dlckFybWVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBhd2FpdEVhcmxpZXJEZWxpdmVyaWVzKFxuICBjdHg6IFdvcmtmbG93T3JjaGVzdHJhdG9yQ29udGV4dCxcbiAgZXZlbnRJbmRleDogbnVtYmVyIHwgdW5kZWZpbmVkLFxuICBraW5kOiBEZWxpdmVyeUtpbmRcbik6IFByb21pc2U8dm9pZD4ge1xuICAvLyBEZWZlbnNpdmU6IHRvbGVyYXRlIGNvbnRleHRzIHRoYXQgcHJlZGF0ZSB0aGlzIGZpZWxkICh0ZXN0IGhhcm5lc3NlcykuXG4gIGlmIChldmVudEluZGV4ID09PSB1bmRlZmluZWQgfHwgIWN0eC5wZW5kaW5nRGVsaXZlcnlCYXJyaWVycykge1xuICAgIHJldHVybjtcbiAgfVxuICBjb25zdCBiYXJyaWVycyA9IGN0eC5wZW5kaW5nRGVsaXZlcnlCYXJyaWVycztcbiAgY29uc3QgZWFybGllcjogUHJvbWlzZTx2b2lkPltdID0gW107XG4gIGZvciAoY29uc3QgW2luZGV4LCBlbnRyeV0gb2YgYmFycmllcnMpIHtcbiAgICBpZiAoIWdhdGVzT24oa2luZCwgZXZlbnRJbmRleCwgaW5kZXgsIGVudHJ5KSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGVhcmxpZXIucHVzaChlbnRyeS5kZWxpdmVyZWQpO1xuICB9XG4gIGlmIChlYXJsaWVyLmxlbmd0aCA+IDApIHtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChlYXJsaWVyKTtcbiAgfVxuICBpZiAoaXNMb2dPcmRlckRyYXdzRW5hYmxlZCgpKSB7XG4gICAgLy8gVW5jb25kaXRpb25hbCwgbm90IGp1c3Qgd2hlbiBhIGJhcnJpZXIgd2FzIHN0aWxsIHJlZ2lzdGVyZWQ6IGFuIGVhcmxpZXJcbiAgICAvLyBkZWxpdmVyeSdzIGJhcnJpZXIgZGVyZWdpc3RlcnMgd2hlbiBpdHMgcmVzb2x2ZSgpIHJ1bnMsIGJ1dCB0aGUgYnJhbmNoXG4gICAgLy8gaXQgd29rZSBtYXkgc3RpbGwgYmUgaG9wcyBhd2F5IGZyb20gaXRzIG5leHQgZHJhdy4gQSBsYXRlciBkZWxpdmVyeVxuICAgIC8vIGNvbnN1bWVkIGFmdGVyIHRoYXQgZGVyZWdpc3RyYXRpb24gc2VlcyBhbiBlbXB0eSBnYXRlIHNldCwgYW5kIHdpdGhvdXRcbiAgICAvLyB0aGlzIGl0IHdvdWxkIHJlc29sdmUgbWlkLWNhc2NhZGUgYW5kIG92ZXJ0YWtlIHRoZSBkcmF3LiBUaGlzIGlzIHRoZSBleGFjdFxuICAgIC8vIGFycml2YWwtb3JkZXIgZGVwZW5kZW5jZSB0aGlzIG1vZGUgZXhpc3RzIHRvIHJlbW92ZS4gQ29zdHMgb25lIHF1aWV0XG4gICAgLy8gbWFjcm90YXNrIHR1cm4gd2hlbiBub3RoaW5nIGlzIGluIGZsaWdodC5cbiAgICBhd2FpdCBxdWllc2NlRWFybGllckNhc2NhZGVzKGN0eCwgZXZlbnRJbmRleCk7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmIChlYXJsaWVyLmxlbmd0aCA+IDApIHtcbiAgICAvLyBBbiBlYXJsaWVyIGRlbGl2ZXJ5IGJlaW5nIFwiZGVsaXZlcmVkXCIgb25seSBtZWFucyBpdHMgYHJlc29sdmUoKWAgcmFuLlxuICAgIC8vIFRoZSBicmFuY2ggaXQgd29rZSBtYXkgbmVlZCBhbiBhcmJpdHJhcnkgbnVtYmVyIG9mIGZ1cnRoZXIgbWljcm90YXNrXG4gICAgLy8gaG9wcyBiZWZvcmUgaXQgcmVhY2hlcyBpdHMgbmV4dCBgdXNlU3RlcGAgY2FsbCBhbmQgZHJhd3MgYSBVTElEOiBhXG4gICAgLy8gYGZvciBhd2FpdGAgb3ZlciBhIGhvb2ssIGZvciBpbnN0YW5jZSwgcmVzdW1lcyB0aGUgZ2VuZXJhdG9yLCBzZXR0bGVzXG4gICAgLy8gdGhlIHByb21pc2UgZnJvbSBgbmV4dCgpYCwgYW5kIG9ubHkgdGhlbiBydW5zIHRoZSBsb29wIGJvZHkuIFJlc29sdmluZ1xuICAgIC8vIHRoaXMgZGVsaXZlcnkgb24gYSBtaWNyb3Rhc2sgd291bGQgbGV0IGl0IG92ZXJ0YWtlIHRoYXQgYnJhbmNoIGFuZFxuICAgIC8vIHJlb3JkZXIgdGhlIFVMSUQgYWxsb2NhdGlvbiBhbnl3YXksIHR1cm5pbmcgdGhlIGd1YXJhbnRlZSBiZWxvdyBpbnRvIGFcbiAgICAvLyBob3AtY291bnQgcmFjZSB0aGF0IGhvbGRzIG9ubHkgZm9yIHRoZSBzaG9ydGVzdCBjb25zdW1lcnMuXG4gICAgLy9cbiAgICAvLyBZaWVsZGluZyBhIG1hY3JvdGFzayBsZXRzIHRoZSBlYXJsaWVyIGJyYW5jaCdzIGVudGlyZSBtaWNyb3Rhc2sgY2hhaW5cbiAgICAvLyBkcmFpbiBmaXJzdCwgd2hhdGV2ZXIgaXRzIGxlbmd0aCwgc28gbG9nIG9yZGVyIHN1cnZpdmVzIHJlZ2FyZGxlc3Mgb2ZcbiAgICAvLyBob3cgdGhlIHdvcmtmbG93IGNvbnN1bWVzIHRoZSBlYXJsaWVyIGRlbGl2ZXJ5LiBPbmx5IGRlbGl2ZXJpZXMgdGhhdFxuICAgIC8vIGFjdHVhbGx5IGhhZCB0byBkZWZlciBwYXkgdGhpcywgc28gdGhlIGNvbW1vbiBzaW5nbGUtZGVsaXZlcnkgZHJhaW4gaXNcbiAgICAvLyB1bmFmZmVjdGVkLlxuICAgIGF3YWl0IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIDApKTtcbiAgfVxufVxuXG4vKiogSGFuZGxlIGZvciBhIHJlZ2lzdGVyZWQgYnJhbmNoLWRlY2lkaW5nIGRlbGl2ZXJ5IGJhcnJpZXIuICovXG5leHBvcnQgaW50ZXJmYWNlIERlbGl2ZXJ5QmFycmllciB7XG4gIC8qKlxuICAgKiBNYXJrIHRoaXMgZGVsaXZlcnkgYXMgZGVsaXZlcmVkIHRvIHRoZSB3b3JrZmxvdy4gUmVzb2x2ZXMgaXRzXG4gICAqIGBkZWxpdmVyZWRgIHByb21pc2Ugc28gYW55IGxhdGVyLWluLWxvZyBkZWxpdmVyeSBnYXRlZCBvbiBpdCAodmlhXG4gICAqIHtAbGluayBhd2FpdEVhcmxpZXJEZWxpdmVyaWVzfSkgbWF5IHByb2NlZWQsIGFuZCByZW1vdmVzIGl0IGZyb20gdGhlXG4gICAqIHJlZ2lzdHJ5LiBJZGVtcG90ZW50LlxuICAgKi9cbiAgbWFya0RlbGl2ZXJlZDogKCkgPT4gdm9pZDtcbiAgLyoqXG4gICAqIE1hcmsgdGhpcyBkZWxpdmVyeSBhcyBjb21taXR0ZWQgdG8gaGFwcGVuaW5nLCBmb3IgYSBiYXJyaWVyIHJlZ2lzdGVyZWRcbiAgICogdW5hcm1lZCAoYSBidWZmZXJlZCBob29rIHBheWxvYWQpIG9uY2UgYSBjb25zdW1lciBoYXMgY2xhaW1lZCBpdC4gRnJvbVxuICAgKiB0aGVuIG9uIGEgbGF0ZXIgc3RlcCByZXN1bHQgbWF5IGJlIG9yZGVyZWQgYmVoaW5kIGl0LiBJZGVtcG90ZW50LlxuICAgKi9cbiAgYXJtOiAoKSA9PiB2b2lkO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVyIGEgYnJhbmNoLWRlY2lkaW5nIGRlbGl2ZXJ5IGF0IGl0cyBldmVudC1sb2cgaW5kZXggc28gdGhhdCBsYXRlclxuICogZGVsaXZlcmllcyBjYW4gYmUgb3JkZXJlZCBzdHJpY3RseSBhZnRlciBpdC4gUmV0dXJucyBhbiBpbmVydCBoYW5kbGUgd2hlblxuICogYHBlbmRpbmdEZWxpdmVyeUJhcnJpZXJzYCBpcyBub3QgaW5pdGlhbGl6ZWQuXG4gKlxuICogUGFzcyBgYXJtZWQ6IGZhbHNlYCBmb3IgYSBkZWxpdmVyeSB3aG9zZSByZXNvbHV0aW9uIHdhaXRzIG9uIHdvcmtmbG93IGNvZGVcbiAqIGFza2luZyBmb3IgaXQgKGEgYnVmZmVyZWQgaG9vayBwYXlsb2FkKTsgY2FsbCBgYXJtKClgIHdoZW4gaXQgZG9lcy5cbiAqXG4gKiBUbyBndWFyYW50ZWUgYSBsYXRlciBkZWxpdmVyeSBnYXRlZCBvbiB0aGlzIG9uZSBjYW4gbmV2ZXIgaGFuZyB3aGVuIHRoaXNcbiAqIGRlbGl2ZXJ5IGlzIGFiYW5kb25lZCAodGhlIHdvcmtmbG93IHRvb2sgYSBkaWZmZXJlbnQgYnJhbmNoIG9yIGlzXG4gKiBzdXNwZW5kaW5nIGFuZCBuZXZlciBvYnNlcnZlcyBpdCksIHRoZSBiYXJyaWVyIGF1dG8tcmVzb2x2ZXMgYXQgaWRsZS5cbiAqXG4gKiBJTlZBUklBTlQgcmVxdWlyZWQgb2YgZXZlcnkgY2FsbCBzaXRlOiBhIGJhcnJpZXIgdGhhdCBpcyBldmVyIGBhcm1lZGAgbXVzdFxuICogYmUgcGFpcmVkIHdpdGggYSBkZWxpdmVyeSBjaGFpbiB0aGF0IHJ1bnMgdW5jb25kaXRpb25hbGx5LCBhdHRhY2hlZCB3aGVuXG4gKiB0aGUgZXZlbnQgaXMgY29uc3VtZWQgKHdhaXRzLCBzdGVwIHJlc3VsdHMsIHdhaXRpbmctY29uc3VtZXIgaG9vayBwYXlsb2FkcyxcbiAqIGFib3J0cyksIG9yIGJ5IHRoZSBgY2xhaW0oKWAgd2hvc2UgaW52b2NhdGlvbiBpcyB3aGF0IGFybXMgaXQgKGJ1ZmZlcmVkXG4gKiBob29rIHBheWxvYWRzKS4gVGhlIGlkbGUgY2hlY2sgKHtAbGluayBzY2hlZHVsZVdoZW5JZGxlfSkgcmVmdXNlcyB0b1xuICogb2JzZXJ2ZSBpZGxlIHdoaWxlIGFuIGFybWVkLCBzZWxmLXJlc29sdmluZyBiYXJyaWVyIGlzIHVuZGVsaXZlcmVkLCBhbmQgdGhlXG4gKiBzYWZldHkgbmV0IGJlbG93IGlzIGl0c2VsZiBpZGxlLWdhdGVkLCBzbyBhbiBhcm1lZCBiYXJyaWVyIHdpdGggbm9cbiAqIHVuY29uZGl0aW9uYWwgY2hhaW4gd291bGQgbGl2ZWxvY2sgZXZlcnkgaWRsZSBjaGVjayBpbiB0aGUgcnVuLCBpbmNsdWRpbmdcbiAqIGl0cyBvd24gcmV0aXJlbWVudC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyRGVsaXZlcnlCYXJyaWVyKFxuICBjdHg6IFdvcmtmbG93T3JjaGVzdHJhdG9yQ29udGV4dCxcbiAgZXZlbnRJbmRleDogbnVtYmVyIHwgdW5kZWZpbmVkLFxuICBraW5kOiBEZWxpdmVyeUtpbmQsXG4gIG9wdGlvbnM6IHsgYXJtZWQ/OiBib29sZWFuIH0gPSB7fVxuKTogRGVsaXZlcnlCYXJyaWVyIHtcbiAgY29uc3QgYmFycmllcnMgPSBjdHgucGVuZGluZ0RlbGl2ZXJ5QmFycmllcnM7XG4gIGlmICghYmFycmllcnMgfHwgZXZlbnRJbmRleCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIHsgbWFya0RlbGl2ZXJlZDogKCkgPT4ge30sIGFybTogKCkgPT4ge30gfTtcbiAgfVxuXG4gIGxldCBkb25lID0gZmFsc2U7XG4gIGNvbnN0IHsgcHJvbWlzZSwgcmVzb2x2ZSB9ID0gd2l0aFJlc29sdmVyczx2b2lkPigpO1xuXG4gIGNvbnN0IGZpbmlzaCA9ICgpID0+IHtcbiAgICBpZiAoZG9uZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBkb25lID0gdHJ1ZTtcbiAgICBpZiAoYmFycmllcnMuZ2V0KGV2ZW50SW5kZXgpID09PSBlbnRyeSkge1xuICAgICAgYmFycmllcnMuZGVsZXRlKGV2ZW50SW5kZXgpO1xuICAgIH1cbiAgICByZXNvbHZlKCk7XG4gIH07XG5cbiAgY29uc3QgZW50cnk6IERlbGl2ZXJ5QmFycmllckVudHJ5ID0ge1xuICAgIGtpbmQsXG4gICAgZGVsaXZlcmVkOiBwcm9taXNlLFxuICAgIGFybWVkOiBvcHRpb25zLmFybWVkID8/IHRydWUsXG4gICAgcmV0aXJlOiBmaW5pc2gsXG4gIH07XG4gIGJhcnJpZXJzLnNldChldmVudEluZGV4LCBlbnRyeSk7XG5cbiAgLy8gU2FmZXR5IG5ldDogaWYgdGhpcyBkZWxpdmVyeSBpcyBuZXZlciBkZWxpdmVyZWQgdG8gdGhlIHdvcmtmbG93IChpdHNcbiAgLy8gYnJhbmNoIHdhcyBub3QgdGFrZW4gLyB0aGUgcnVuIGlzIHN1c3BlbmRpbmcsIG9yIGEgYnVmZmVyZWQgaG9vayBwYXlsb2FkXG4gIC8vIGlzIG9ubHkgY2xhaW1lZCBhZnRlciBhIGxhdGVyIGRlbGl2ZXJ5IHRoZSB3b3JrZmxvdyBpcyBzdGlsbCB3YWl0aW5nIG9uKSxcbiAgLy8gaXQgaXMgcmV0aXJlZCBhdCBpZGxlIHNvIGEgbGF0ZXIgZGVsaXZlcnkgZ2F0ZWQgb24gaXQgY2Fubm90IGRlYWRsb2NrIGFuZFxuICAvLyB0aGUgcmVnaXN0cnkgY2Fubm90IGxlYWsgYW4gZW50cnkgcGVyIGFiYW5kb25lZCBkZWxpdmVyeS4gUmV0aXJlbWVudCBnb2VzXG4gIC8vIHRocm91Z2ggdGhlIGNvbnRleHQncyBzaW5nbGUgb3JkZXJlZCBkaXNwZW5zZXIgcmF0aGVyIHRoYW4gYSBwZXItYmFycmllclxuICAvLyBpZGxlIHBvbGwuIFNlZSB7QGxpbmsgZW5zdXJlQmFycmllclNhZmV0eU5ldH0gZm9yIHdoeSB0aGUgT1JERVIgb2YgdGhlc2VcbiAgLy8gcmV0aXJlbWVudHMgaXMgbG9hZC1iZWFyaW5nLlxuICBlbnN1cmVCYXJyaWVyU2FmZXR5TmV0KGN0eCk7XG5cbiAgcmV0dXJuIHtcbiAgICBtYXJrRGVsaXZlcmVkOiBmaW5pc2gsXG4gICAgYXJtOiAoKSA9PiB7XG4gICAgICBlbnRyeS5hcm1lZCA9IHRydWU7XG4gICAgfSxcbiAgfTtcbn1cblxuLyoqXG4gKiBDb250ZXh0cyB3aG9zZSBiYXJyaWVyIHNhZmV0eS1uZXQgZGlzcGVuc2VyIGlzIGN1cnJlbnRseSBhcm1lZC4gTW9kdWxlLWxldmVsXG4gKiBzbyB0aGUgY29udGV4dCBpbnRlcmZhY2UgKGNvbnN0cnVjdGVkIGxpdGVyYWxseSBieSBtYW55IHRlc3QgaGFybmVzc2VzKVxuICogbmVlZHMgbm8gbmV3IGZpZWxkOyBlbnRyaWVzIGRyb3Agd2l0aCB0aGUgY29udGV4dC5cbiAqL1xuLy8gcGVyLWNvcHktb2s6IGtleWVkIG9uIHRoZSBvcmNoZXN0cmF0b3IgY29udGV4dCBvYmplY3QsIGFuZCBhIGNvbnRleHQgaXMgYXJtZWRcbi8vIGFuZCBvYnNlcnZlZCBieSB0aGUgc2FtZSBjb3B5IHRoYXQgY3JlYXRlZCBpdC4gRW50cmllcyBjYW4gbmV2ZXIgYmUgbG9va2VkIHVwXG4vLyBmcm9tIGFub3RoZXIgY29weSBiZWNhdXNlIHRoYXQgY29weSBoYXMgbm8gcmVmZXJlbmNlIHRvIHRoZSBrZXkuXG5jb25zdCBhY3RpdmVCYXJyaWVyU2FmZXR5TmV0cyA9IG5ldyBXZWFrU2V0PFdvcmtmbG93T3JjaGVzdHJhdG9yQ29udGV4dD4oKTtcblxuLyoqXG4gKiBUaGUgYmFycmllciByZWdpc3RyeSdzIHNhZmV0eSBuZXQ6IE9ORSBpZGxlLWdhdGVkIGRpc3BlbnNlciBwZXIgY29udGV4dCB0aGF0XG4gKiByZXRpcmVzLCBhdCBlYWNoIG9ic2VydmF0aW9uIG9mIGRlbGl2ZXJ5IGlkbGUsIG9ubHkgdGhlIExPV0VTVC1pbmRleCBlbnRyeVxuICogc3RpbGwgcmVnaXN0ZXJlZCwgdGhlbiB5aWVsZHMgc28gdGhlIGNoYWluIGl0IHJlbGVhc2VkIGNhbiBydW4gYmVmb3JlIHRoZVxuICogbmV4dCByZXRpcmVtZW50IGlzIGNvbnNpZGVyZWQuXG4gKlxuICogV2h5IG9uZSBvcmRlcmVkIGRpc3BlbnNlciBhbmQgbm90IGEgcG9sbCBwZXIgYmFycmllciAod2hpY2ggaXMgd2hhdCB0aGlzXG4gKiByZXBsYWNlZCk6IHRoZSBvcmRlciBvZiBzYWZldHktbmV0IHJldGlyZW1lbnRzIGRlY2lkZXMgdGhlIGRlbGl2ZXJ5IG9yZGVyIG9mXG4gKiBldmVyeSBjaGFpbiBwYXJrZWQgYmVoaW5kIGFuIHVuY2xhaW1lZCBidWZmZXJlZCBob29rIHBheWxvYWQ6IGEgaG9vayB0aGVcbiAqIHdvcmtmbG93IG5ldmVyIHJlYWRzIChhIGZpcmUtYW5kLWZvcmdldCBgY3JlYXRlSG9va2ApIHBhcmtzIGV2ZXJ5IGxhdGVyXG4gKiBhcm1lZCB3YWl0L2hvb2sgYmVoaW5kIGEgYmFycmllciB0aGF0IG9ubHkgdGhpcyBuZXQgY2FuIHJldGlyZS4gUGVyLWJhcnJpZXJcbiAqIHBvbGxzIGZpcmUgaW4gd2hhdGV2ZXIgb3JkZXIgdGhlaXIgcmUtYXJtIGN5Y2xlcyBsYW5kLCBhbmQgZWFjaCByZS1hcm1cbiAqIGF0dGFjaGVzIHRvIGEgYHByb21pc2VRdWV1ZWAgdGhhdCBncm93cyBiZXR3ZWVuIGNoZWNrcywgc28gd2l0aCBzZXZlcmFsXG4gKiBwYXJrZWQgc2VnbWVudHMgdGhlIHJlbGVhc2Ugb3JkZXIgZGVjYXlzIHRvIHRpbWluZyBub2lzZS4gRHJhd3MgKGB1c2VTdGVwYFxuICogY29ycmVsYXRpb24gaWRzKSB0aGVuIGRlcGVuZCBvbiB3aGljaCBzZWdtZW50IGhhcHBlbmVkIHRvIHJlbGVhc2UgZmlyc3Q6XG4gKiBjb25jcmV0ZWx5LCBvbiBob3cgTVVDSCBsb2cgdGhlIHJlcGxheSBsb2FkZWQsIHNpbmNlIHRoYXQgZGVjaWRlcyB3aGF0IGlzIGluXG4gKiB0aGUgcmVnaXN0cnkuIFRoYXQgaXMgdGhlIG1lY2hhbmlzbSBiZWhpbmQgc2xvdC1tb2RlIENPUlJVUFRFRF9FVkVOVF9MT0cgb25cbiAqIHN0b3JtLXNoYXBlZCBydW5zIChzZWUgc3Rvcm0tbG9nLXJlcGxheS50ZXN0LnRzLCBidWlsdCBmcm9tIGEgcHJvZHVjdGlvblxuICogbG9nKTogdHdvIHJlcGxheXMgb2YgdGhlIHNhbWUgcnVuIGhvbGRpbmcgZGlmZmVyZW50LWxlbmd0aCBwcmVmaXhlcyBib3VuZFxuICogdGhlIHNhbWUgY29ycmVsYXRpb24gb3JkaW5hbCB0byBkaWZmZXJlbnQgc3RlcHMuXG4gKlxuICogUmV0aXJpbmcgbG93ZXN0LWZpcnN0IGlzIG5vdCBtZXJlbHkgdGlkeSwgaXQgaXMgdGhlIG9ubHkgb3JkZXIgdGhhdCBjYW5ub3RcbiAqIGludmVydCB0aGUgbG9nOiBldmVyeSBnYXRlIHBvaW50cyBmcm9tIGEgaGlnaGVyIGluZGV4IHRvIGEgc3RyaWN0bHkgbG93ZXJcbiAqIG9uZSwgc28gYXQgZGVsaXZlcnkgaWRsZSB0aGUgbG93ZXN0IHVuZGVsaXZlcmVkIGVudHJ5IGdhdGVzIG9uIG5vdGhpbmdcbiAqIHN0aWxsIHJlZ2lzdGVyZWQ6IGl0IGlzIHRoZSBoZWFkIG9mIGV2ZXJ5IHBhcmtlZCBjaGFpbiAoaW4gcHJhY3RpY2UsIHRoZVxuICogdW5jbGFpbWVkIHBheWxvYWQgaXRzZWxmKS4gUmVsZWFzaW5nIGl0IGxldHMgdGhlIGNoYWluIGFib3ZlIGRlbGl2ZXJcbiAqIHRocm91Z2ggdGhlIG9yZGluYXJ5IGJhcnJpZXIgb3JkZXI7IGFueXRoaW5nIHRoZSByZWxlYXNlIHdha2VzIGZsaXBzXG4gKiB7QGxpbmsgaGFzUGFya2VkQ29tbWl0dGVkRGVsaXZlcnl9IGJhY2sgdG8gdHJ1ZSwgd2hpY2ggcmUtYmxvY2tzIHRoaXNcbiAqIGRpc3BlbnNlciB1bnRpbCB0aGUgY2hhaW4gaGFzIGZ1bGx5IGRyYWluZWQuIEEgaGlnaGVyIGVudHJ5IG11c3QgbmV2ZXIgYmVcbiAqIHJldGlyZWQgd2hpbGUgYSBsb3dlciBvbmUgaXMgcmVnaXN0ZXJlZCwgd2hpY2ggaXMgZXhhY3RseSB0aGUgaW52ZXJzaW9uXG4gKiBkZXNjcmliZWQgb24ge0BsaW5rIGF3YWl0RWFybGllckRlbGl2ZXJpZXN9LlxuICpcbiAqIFRoZSBkaXNwZW5zZXIgZ29lcyBkb3JtYW50IHdoZW4gdGhlIHJlZ2lzdHJ5IGVtcHRpZXMgYW5kIGlzIHJlLWFybWVkIGJ5IHRoZVxuICogbmV4dCByZWdpc3RyYXRpb24sIHNvIGFuIGlkbGUgY29udGV4dCBob2xkcyBubyBsaXZlIHRpbWVyLlxuICovXG5mdW5jdGlvbiBlbnN1cmVCYXJyaWVyU2FmZXR5TmV0KGN0eDogV29ya2Zsb3dPcmNoZXN0cmF0b3JDb250ZXh0KTogdm9pZCB7XG4gIGNvbnN0IGJhcnJpZXJzID0gY3R4LnBlbmRpbmdEZWxpdmVyeUJhcnJpZXJzO1xuICBpZiAoIWJhcnJpZXJzIHx8IGFjdGl2ZUJhcnJpZXJTYWZldHlOZXRzLmhhcyhjdHgpKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGFjdGl2ZUJhcnJpZXJTYWZldHlOZXRzLmFkZChjdHgpO1xuICBjb25zdCByZWFybSA9ICgpID0+IHtcbiAgICBzZXRUaW1lb3V0KGNoZWNrLCAwKTtcbiAgfTtcbiAgLy8gQSByZWplY3RlZCBwcm9taXNlUXVldWUgc2V0dGxlcyBpbW1lZGlhdGVseSBhbmQgZm9yZXZlciwgc28gcmUtYXJtaW5nXG4gIC8vIHRocm91Z2ggaXQgYXQgdGhlIG5vcm1hbCBjYWRlbmNlIHdvdWxkIGRlZ2VuZXJhdGUgaW50byBhIGJ1c3kgbG9vcCBvbiBhblxuICAvLyBhYmFuZG9uZWQgY29udGV4dC4gQmFjayBvZmYgaW5zdGVhZDogY29ycmVjdG5lc3Mgb25seSBuZWVkcyB0aGUgZGlzcGVuc2VyXG4gIC8vIHRvIHN0aWxsIGV4aXN0LCBzaW5jZSB0aGUgcmVnaXN0cnkgZ2F0ZXMgc3VzcGVuc2lvbiB2aWEgaXNEZWxpdmVyeUlkbGVcbiAgLy8gYW5kIGEgZGVhZCBkaXNwZW5zZXIgd291bGQgd2VkZ2UgdGhlIHJ1bi5cbiAgY29uc3QgcmVhcm1BZnRlclJlamVjdGlvbiA9ICgpID0+IHtcbiAgICBzZXRUaW1lb3V0KGNoZWNrLCA1MCk7XG4gIH07XG4gIGNvbnN0IGNoZWNrID0gKCkgPT4ge1xuICAgIGlmIChiYXJyaWVycy5zaXplID09PSAwKSB7XG4gICAgICAvLyBEb3JtYW50LiBUaGUgbmV4dCByZWdpc3RlckRlbGl2ZXJ5QmFycmllciByZS1hcm1zLlxuICAgICAgYWN0aXZlQmFycmllclNhZmV0eU5ldHMuZGVsZXRlKGN0eCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICghY2FuUmV0aXJlQWJhbmRvbmVkQmFycmllcnMoY3R4KSkge1xuICAgICAgLy8gQSBkZWxpdmVyeSBpcyBoeWRyYXRpbmcgb3IgY29tbWl0dGVkLWJ1dC1wYXJrZWQgb24gaXRzIGRlZmVycmFsOyBsZXRcbiAgICAgIC8vIHRoZSBxdWV1ZSBkcmFpbiBhbmQgcmUtY2hlY2sgYSB0aWNrIGxhdGVyIChzYW1lIGNhZGVuY2UgYXNcbiAgICAgIC8vIHNjaGVkdWxlV2hlbklkbGUpLlxuICAgICAgY3R4LnByb21pc2VRdWV1ZS50aGVuKHJlYXJtLCByZWFybUFmdGVyUmVqZWN0aW9uKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gSWRsZSB3aXRoIGVudHJpZXMgbGVmdDogbm90aGluZyByZW1haW5pbmcgZGVsaXZlcnMgb24gaXRzIG93biwgc29cbiAgICAvLyByZWxlYXNlIHBhcmtlZCBjaGFpbnMgZnJvbSB0aGUgaGVhZDogbG93ZXN0IGluZGV4IGZpcnN0LCBvbmUgYXQgYVxuICAgIC8vIHRpbWUsIHJlLXJlYWRpbmcgaWRsZSBiZXR3ZWVuIHJldGlyZW1lbnRzLiBBIHJldGlyZW1lbnQgdGhhdCB3YWtlcyBhXG4gICAgLy8gY2hhaW4gZmxpcHMge0BsaW5rIGhhc1BhcmtlZENvbW1pdHRlZERlbGl2ZXJ5fSBzeW5jaHJvbm91c2x5IChpdCBpc1xuICAgIC8vIGNvbXB1dGVkIGZyb20gdGhlIHJlZ2lzdHJ5IHRoaXMgbG9vcCBqdXN0IG11dGF0ZWQpLCB3aGljaCBzdG9wcyB0aGVcbiAgICAvLyBzd2VlcCBzbyB0aGUgY2hhaW4gZGVsaXZlcnMgYmVmb3JlIGFueXRoaW5nIGFib3ZlIGl0IGlzIHJlbGVhc2VkLiBBXG4gICAgLy8gcmV0aXJlbWVudCB0aGF0IHdha2VzIG5vdGhpbmcgKGEgc3RhbGUgcGF5bG9hZCBubyBkZWxpdmVyeSBnYXRlcyBvbilcbiAgICAvLyBrZWVwcyB0aGUgc3dlZXAgZ29pbmcsIHNvIGEgYmFja2xvZyBvZiB0aG9zZSBkcmFpbnMgaW4gT05FIGlkbGVcbiAgICAvLyBvYnNlcnZhdGlvbiwgc2luY2UgcGFjaW5nIHRoZW0gb25lIHBlciB0aW1lciB0aWNrIHdvdWxkIGhvbGRcbiAgICAvLyBjb25zdW1lZC1idXQtdW5kZWxpdmVyZWQgZXZlbnRzIGhvc3RhZ2UgbG9uZyBlbm91Z2ggdG8gdHJpcCB0aGUgZXZlbnRzXG4gICAgLy8gY29uc3VtZXIncyB1bmNvbnN1bWVkLWV2ZW50IGRlYWRsaW5lIGFuZCBmYWlsIGhlYWx0aHkgcmVwbGF5cy5cbiAgICB3aGlsZSAoYmFycmllcnMuc2l6ZSA+IDAgJiYgY2FuUmV0aXJlQWJhbmRvbmVkQmFycmllcnMoY3R4KSkge1xuICAgICAgbGV0IGxvd2VzdEluZGV4OiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gICAgICBsZXQgbG93ZXN0RW50cnk6IERlbGl2ZXJ5QmFycmllckVudHJ5IHwgdW5kZWZpbmVkO1xuICAgICAgZm9yIChjb25zdCBbaW5kZXgsIGVudHJ5XSBvZiBiYXJyaWVycykge1xuICAgICAgICBpZiAobG93ZXN0SW5kZXggPT09IHVuZGVmaW5lZCB8fCBpbmRleCA8IGxvd2VzdEluZGV4KSB7XG4gICAgICAgICAgbG93ZXN0SW5kZXggPSBpbmRleDtcbiAgICAgICAgICBsb3dlc3RFbnRyeSA9IGVudHJ5O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBsb3dlc3RFbnRyeT8ucmV0aXJlKCk7XG4gICAgfVxuICAgIHNldFRpbWVvdXQoY2hlY2ssIDApO1xuICB9O1xuICBzZXRUaW1lb3V0KGNoZWNrLCAwKTtcbn1cblxuLyoqXG4gKiBXaGV0aGVyIHRoZSBzYWZldHktbmV0IGRpc3BlbnNlciBtYXkgcmV0aXJlIGFiYW5kb25lZCBiYXJyaWVycyByaWdodCBub3c6XG4gKiBubyBoeWRyYXRpb24gaW4gZmxpZ2h0IGFuZCBubyBjb21taXR0ZWQgZGVsaXZlcnkgc3RpbGwgd29ya2luZyB0aHJvdWdoIGl0c1xuICogZGV0YWNoZWQgZGVmZXJyYWwuIFRoaXMgaXMgZGVsaWJlcmF0ZWx5IFdFQUtFUiB0aGFuIHtAbGluayBpc0RlbGl2ZXJ5SWRsZX06XG4gKiB0aGUgZGlzcGVuc2VyIGlzIHdoYXQgZW1wdGllcyB0aGUgcmVnaXN0cnksIHNvIGdhdGluZyBpdCBvbiByZWdpc3RyeVxuICogZW1wdGluZXNzIHdvdWxkIGdhdGUgaXRzIG93biB3b3JrLlxuICovXG5mdW5jdGlvbiBjYW5SZXRpcmVBYmFuZG9uZWRCYXJyaWVycyhjdHg6IFdvcmtmbG93T3JjaGVzdHJhdG9yQ29udGV4dCk6IGJvb2xlYW4ge1xuICByZXR1cm4gY3R4LnBlbmRpbmdEZWxpdmVyaWVzID09PSAwICYmICFoYXNQYXJrZWRDb21taXR0ZWREZWxpdmVyeShjdHgpO1xufVxuXG4vKipcbiAqIFdoZXRoZXIgc29tZSByZWdpc3RlcmVkIGJyYW5jaC1kZWNpZGluZyBkZWxpdmVyeSBpcyBnb2luZyB0byByZWFjaCB0aGVcbiAqIHdvcmtmbG93IHdpdGhvdXQgYW55IGZ1cnRoZXIgaGVscCAoaXQgaXMgYXJtZWQgYW5kIG5vdCB0cmFuc2l0aXZlbHkgcGFya2VkXG4gKiBiZWhpbmQgYW4gdW5jbGFpbWVkIGJ1ZmZlcmVkIHBheWxvYWQsIHNlZSB7QGxpbmsgcmVzb2x2ZXNPbkl0c093bn0pIGJ1dFxuICogaGFzIG5vdCBiZWVuIGhhbmRlZCBvdmVyIHlldC5cbiAqXG4gKiBUaGlzIGlzIHRoZSBkZWxpdmVyeSBzdGF0ZSBgcGVuZGluZ0RlbGl2ZXJpZXNgIGNhbm5vdCBzZWUuIFRoYXQgY291bnRlclxuICogY292ZXJzIHRoZSBoeWRyYXRpb24gd2luZG93IGluc2lkZSBhIHNlcmlhbCBgcHJvbWlzZVF1ZXVlYCBzbG90IGFuZCBpc1xuICogcmVsZWFzZWQgdGhlcmUsIHdoaWxlIHRoZSBkZWxpdmVyeSdzIGByZXNvbHZlKClgIHJ1bnMgbGF0ZXIsIGZyb20gYVxuICogZGV0YWNoZWQgY29udGludWF0aW9uIGJlaGluZCB7QGxpbmsgYXdhaXRFYXJsaWVyRGVsaXZlcmllc30sIGluY2x1ZGluZyBpdHNcbiAqIG1hY3JvdGFzayB5aWVsZCB3aGVuZXZlciB0aGUgZGVsaXZlcnkgaGFkIHRvIGRlZmVyLiBSZXBsYXlpbmcgYSBiYXRjaCBvZiBOXG4gKiBwYXJhbGxlbCBzdGVwIHJlc3VsdHMgY29uc3VtZWQgaW4gb25lIGRyYWluIHdpbmRvdyBsZWF2ZXMgTi0xIG9mIHRoZW1cbiAqIHBhcmtlZCBvbiB0aGF0IHlpZWxkIHdpdGggYHBlbmRpbmdEZWxpdmVyaWVzYCBhbHJlYWR5IGF0IDAuIEFuIGlkbGUgY2hlY2tcbiAqIGFybWVkIGR1cmluZyB0aGUgc2FtZSB3aW5kb3cgKGEgcGVuZGluZyBgc2xlZXAoKWAgYXJtcyBvbmUgb24gZXZlcnkgcmVwbGF5KVxuICogY291bGQgdGhlbiBvYnNlcnZlIFwiaWRsZVwiIG1pZC1kZWZlcnJhbCBhbmQgcmFpc2UgYSBgV29ya2Zsb3dTdXNwZW5zaW9uYFxuICogQkVGT1JFIHRoZSB3b3JrZmxvdydzIG93biBjb250aW51YXRpb25zIHJhbjogYSBzdXNwZW5zaW9uIGNhcnJ5aW5nIG5vbmUgb2ZcbiAqIHRoZSBmb2xsb3ctdXAgd29yayB0aGUgYmF0Y2ggd2FzIGFib3V0IHRvIGNyZWF0ZSwgd2hpY2ggdGhlIHJ1bnRpbWVcbiAqIGR1dGlmdWxseSBzY2hlZHVsZXMgYXMgbm90aGluZywgbGVhdmluZyB0aGUgcnVuIGRvcm1hbnQgdW50aWwgYW4gdW5yZWxhdGVkXG4gKiB0aW1lciBmaXJlcyAodmVyY2VsL3dvcmtmbG93IzMxODMpLlxuICpcbiAqIERlbGl2ZXJpZXMgdGhhdCBkbyBOT1QgcmVzb2x2ZSBvbiB0aGVpciBvd24gbXVzdCBiZSBleGNsdWRlZCwgbm90IGZvclxuICogYWNjdXJhY3kgYnV0IGZvciB0ZXJtaW5hdGlvbjogYW4gdW5jbGFpbWVkIGJ1ZmZlcmVkIGhvb2sgcGF5bG9hZCBpcyByZXRpcmVkXG4gKiBCWSB0aGUgaWRsZSBzYWZldHkgbmV0IGluIHtAbGluayByZWdpc3RlckRlbGl2ZXJ5QmFycmllcn0sIHNvIGNvdW50aW5nIGl0XG4gKiBoZXJlIHdvdWxkIGdhdGUgaXRzIG93biByZXRpcmVtZW50LiBUaGF0IHJlYXNvbmluZyBleHRlbmRzIHRvIHdoYXRldmVyIGlzXG4gKiBwYXJrZWQgYmVoaW5kIHN1Y2ggYSBwYXlsb2FkIChhIHdhaXQsIGFuZCBhIHN0ZXAgZ2F0aW5nIG9uIHRoYXQgd2FpdCkgZm9yXG4gKiB0aGUgc2FtZSByZWFzb246IHRoZSB3aG9sZSBjaGFpbiBtb3ZlcyBvbmx5IG9uY2UgdGhlIG5ldCBmaXJlcywgYW5kIGl0XG4gKiBjYW5ub3QgZmlyZSB3aGlsZSB0aGUgY2hhaW4gaXMgY291bnRlZC4gU2VsZi1yZXNvbHZpbmcgZGVsaXZlcmllcyBhbHdheXNcbiAqIGRlbGl2ZXIgZnJvbSB0aGVpciBvd24gY2hhaW5zIChzZWUgdGhlIElOVkFSSUFOVCBvblxuICoge0BsaW5rIHJlZ2lzdGVyRGVsaXZlcnlCYXJyaWVyfSkgYW5kIG5ldmVyIG5lZWQgdGhhdCBuZXQsIHNvIHdhaXRpbmcgb25cbiAqIHRoZW0gaXMgZGVhZGxvY2stZnJlZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhhc1BhcmtlZENvbW1pdHRlZERlbGl2ZXJ5KFxuICBjdHg6IFdvcmtmbG93T3JjaGVzdHJhdG9yQ29udGV4dFxuKTogYm9vbGVhbiB7XG4gIGNvbnN0IGJhcnJpZXJzID0gY3R4LnBlbmRpbmdEZWxpdmVyeUJhcnJpZXJzO1xuICBpZiAoIWJhcnJpZXJzIHx8IGJhcnJpZXJzLnNpemUgPT09IDApIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgLy8gU2hhcmVkIGFjcm9zcyB0aGlzIGNhbGwgb25seS4gU2VlIGByZXNvbHZlc09uSXRzT3duYC5cbiAgY29uc3Qgc2VsZlJlc29sdmluZyA9IG5ldyBNYXA8bnVtYmVyLCBib29sZWFuPigpO1xuICBmb3IgKGNvbnN0IFtpbmRleCwgZW50cnldIG9mIGJhcnJpZXJzKSB7XG4gICAgaWYgKHJlc29sdmVzT25JdHNPd24oYmFycmllcnMsIGluZGV4LCBlbnRyeSwgc2VsZlJlc29sdmluZykpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG5cbi8qKlxuICogV2hldGhlciBubyBkYXRhIGRlbGl2ZXJ5IChzdGVwIHJlc3VsdCwgaG9vayBwYXlsb2FkKSBpcyBpbiBmbGlnaHQgcmlnaHQgbm93LlxuICpcbiAqIFwiSW4gZmxpZ2h0XCIgaXMgdHdvIGRpc3RpbmN0IHdpbmRvd3MsIGVhY2ggd2l0aCBpdHMgb3duIGd1YXJkOlxuICogYHBlbmRpbmdEZWxpdmVyaWVzID4gMGAgY292ZXJzIGh5ZHJhdGlvbiBpbnNpZGUgdGhlIHNlcmlhbCBxdWV1ZSBzbG90cywgYW5kXG4gKiB7QGxpbmsgaGFzUGFya2VkQ29tbWl0dGVkRGVsaXZlcnl9IGNvdmVycyB0aGUgZGV0YWNoZWQgZ2FwIGJldHdlZW4gYSBzbG90XG4gKiByZWxlYXNpbmcgdGhhdCBjb3VudGVyIGFuZCB0aGUgZGVsaXZlcnkncyBgcmVzb2x2ZSgpYCBhY3R1YWxseSBydW5uaW5nLFxuICogZGVsaWJlcmF0ZWx5IG91dHNpZGUgYHBlbmRpbmdEZWxpdmVyaWVzYCAoc2VlIHN0ZXAudHMpLCBhbmQgaW52aXNpYmxlIHRvIGl0LlxuICpcbiAqIEFueXRoaW5nIHRoYXQgZGVjaWRlcyBhIHJlcGxheSBpcyBvdmVyLCBvciB0aGF0IGEgcmVwbGF5IHdlbnQgd3JvbmcsIGhhcyB0b1xuICogY29uc3VsdCB0aGlzIGZpcnN0OiB3aGlsZSBpdCBpcyBmYWxzZSB0aGUgd29ya2Zsb3cgVk0gaXMgbWlkLXJlYWN0aW9uLCBzb1xuICogd2hhdCBpdCBoYXMgYW5kIGhhcyBub3QgZG9uZSB5ZXQgc2F5cyBub3RoaW5nIGFib3V0IHRoZSBydW4uIFR3byBjYWxsZXJzXG4gKiByZWFkIGl0LCBmb3IgdGhlIHR3byBzdWNoIGRlY2lzaW9uczoge0BsaW5rIHNjaGVkdWxlV2hlbklkbGV9IGZvciB0aGVcbiAqIHN1c3BlbnNpb24sIGFuZCB0aGUgZXZlbnRzIGNvbnN1bWVyJ3MgdW5jb25zdW1lZC1ldmVudCBjaGVjayBmb3IgZGl2ZXJnZW5jZS5cbiAqXG4gKiBBIG5vbi1lbXB0eSBiYXJyaWVyIHJlZ2lzdHJ5IGNvdW50cyBhcyBpbiBmbGlnaHQsIGV2ZW4gd2hlbiBldmVyeSByZW1haW5pbmdcbiAqIGVudHJ5IGlzIHBhcmtlZCBiZWhpbmQgYW4gdW5jbGFpbWVkIGJ1ZmZlcmVkIHBheWxvYWQuIFRob3NlIGVudHJpZXMgb25seVxuICogbW92ZSB3aGVuIHRoZSBzYWZldHktbmV0IGRpc3BlbnNlciByZXRpcmVzIHRoZW0gKGxvd2VzdC1maXJzdCwgc2VlXG4gKiB7QGxpbmsgZW5zdXJlQmFycmllclNhZmV0eU5ldH0pLCBhbmQgdGhlIGRlbGl2ZXJpZXMgdGhleSByZWxlYXNlIGFyZSByZWFsXG4gKiB3b3JrZmxvdyByZWFjdGlvbnM6IGEgc3VzcGVuc2lvbiByYWlzZWQgYmVmb3JlIHRoZXkgcnVuIHdvdWxkIGJlIGNvbXB1dGVkXG4gKiBmcm9tIGEgVk0gdGhhdCBoYXMgbm90IHNlZW4gdGhlbSwgc2NoZWR1bGluZyBub25lIG9mIHRoZWlyIGZvbGxvdy11cCB3b3JrXG4gKiBhbmQgbGVhdmluZyB0aGUgcnVuIGRvcm1hbnQgKHRoZSB2ZXJjZWwvd29ya2Zsb3cjMzE4MyBzaGFwZSkuIFRoZSBkaXNwZW5zZXJcbiAqIGl0c2VsZiBpcyBnYXRlZCBvbiB7QGxpbmsgY2FuUmV0aXJlQWJhbmRvbmVkQmFycmllcnN9LCB0aGUgd2Vha2VyIHByZWRpY2F0ZVxuICogd2l0aG91dCB0aGUgcmVnaXN0cnkgdGVybSwgcHJlY2lzZWx5IHNvIGl0IGNhbiBkbyB0aGUgZHJhaW5pbmcgdGhhdCB0aGlzXG4gKiBwcmVkaWNhdGUgd2FpdHMgZm9yOyByZWdpc3RyeSBzaXplIHN0cmljdGx5IGRlY3JlYXNlcyBhdCBlYWNoIHJldGlyZW1lbnQsXG4gKiBzbyBpZGxlIGlzIGFsd2F5cyByZWFjaGVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNEZWxpdmVyeUlkbGUoY3R4OiBXb3JrZmxvd09yY2hlc3RyYXRvckNvbnRleHQpOiBib29sZWFuIHtcbiAgcmV0dXJuIChcbiAgICBjdHgucGVuZGluZ0RlbGl2ZXJpZXMgPT09IDAgJiZcbiAgICAoIWN0eC5wZW5kaW5nRGVsaXZlcnlCYXJyaWVycyB8fCBjdHgucGVuZGluZ0RlbGl2ZXJ5QmFycmllcnMuc2l6ZSA9PT0gMClcbiAgKTtcbn1cblxuLyoqXG4gKiBTY2hlZHVsZSBhIGNhbGxiYWNrIHRvIGZpcmUgb25seSBhZnRlciBhbGwgcGVuZGluZyBkYXRhIGRlbGl2ZXJpZXNcbiAqIChzdGVwIHJlc3VsdHMsIGhvb2sgcGF5bG9hZHMpIGFuZCBhc3luYyBkZXNlcmlhbGl6YXRpb24gaGF2ZSBjb21wbGV0ZWQuXG4gKiBVc2VzIGEgcG9sbGluZyBsb29wOiBzZXRUaW1lb3V0KDApIOKGkiBjaGVjayBwZW5kaW5nRGVsaXZlcmllcyBhbmQgdGhlXG4gKiBiYXJyaWVyIHJlZ2lzdHJ5IOKGkiBpZiBhbnl0aGluZyBpcyBzdGlsbCBpbiBmbGlnaHQsIHdhaXQgZm9yIHByb21pc2VRdWV1ZSDihpJcbiAqIHJlcGVhdC4gVGhpcyBoYW5kbGVzIHRoZSBtdWx0aS1yb3VuZCBkZWxpdmVyeSBwYXR0ZXJuIHdoZXJlIGVhY2ggaG9va1xuICogcGF5bG9hZCBkZWxpdmVyeSBjeWNsZSBhcHBlbmRzIG5ldyBhc3luYyB3b3JrIHRvIHRoZSBwcm9taXNlUXVldWUuIFdoYXRcbiAqIGNvdW50cyBhcyBpbiBmbGlnaHQgaXMge0BsaW5rIGlzRGVsaXZlcnlJZGxlfS5cbiAqXG4gKiBUaGUgaW5pdGlhbCBgc2V0VGltZW91dCgwKWAgbWFjcm90YXNrIGlzIGxvYWQtYmVhcmluZyBhbmQgbXVzdCBOT1QgYmVcbiAqIGRvd25ncmFkZWQgdG8gYSBtaWNyb3Rhc2sgKGBxdWV1ZU1pY3JvdGFza2AvYFByb21pc2UucmVzb2x2ZSgpLnRoZW5gKS5cbiAqIGBwZW5kaW5nRGVsaXZlcmllc2Agb25seSBndWFyZHMgdGhlIGhvc3Qtc2lkZSBoeWRyYXRpb24gd2luZG93OyBiZXR3ZWVuIGFcbiAqIGRlbGl2ZXJ5J3MgYHJlc29sdmUoKWAgYW5kIHRoZSB3b3JrZmxvdyBWTSBib2R5IHJ1bm5pbmcgaXRzIGNvbnRpbnVhdGlvbiB0b1xuICogcmVnaXN0ZXIgdGhlIG5leHQgc3Vic2NyaWJlciwgYHBlbmRpbmdEZWxpdmVyaWVzYCBpcyBhbHJlYWR5IDAgZXZlbiB0aG91Z2hcbiAqIHRoZSBWTSBpcyBtaWQtcmVhY3Rpb24uIE5vZGUgZG9lcyBub3QgZ3VhcmFudGVlIGEgbWljcm90YXNrIHNjaGVkdWxlZCBpblxuICogdGhlIGhvc3QgY29udGV4dCBzZXR0bGVzIGFmdGVyIHRoZSBjcm9zcy1WTSBwcm9taXNlIGNoYWluIChyZXNvbHZlIGluIGhvc3RcbiAqIOKGkiB3b3JrZmxvdyBjb2RlIGluIFZNIOKGkiBzdWJzY3JpYmUgYmFjayBpbiBob3N0KTsgdGhlIG1hY3JvdGFzayBib3VuZGFyeVxuICogZ2l2ZXMgdGhhdCBjaGFpbiB0aW1lIHRvIHJ1biwgc28gdGhlIHN1c3BlbnNpb24gZG9lcyBub3QgcHJlZW1wdCBhIHNpYmxpbmdcbiAqIGRlbGl2ZXJ5IHN0aWxsIGluIGZsaWdodC4gRW1waXJpY2FsbHksIHJlcGxhY2luZyBpdCB3aXRoIGBxdWV1ZU1pY3JvdGFza2BcbiAqIGJyZWFrcyBob29rL3NsZWVwIGBQcm9taXNlLnJhY2VgIG9yZGVyaW5nIChDb3JydXB0ZWRFdmVudExvZ0Vycm9yKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNjaGVkdWxlV2hlbklkbGUoXG4gIGN0eDogV29ya2Zsb3dPcmNoZXN0cmF0b3JDb250ZXh0LFxuICBmbjogKCkgPT4gdm9pZFxuKTogdm9pZCB7XG4gIGNvbnN0IGNoZWNrID0gKCkgPT4ge1xuICAgIGlmICghaXNEZWxpdmVyeUlkbGUoY3R4KSkge1xuICAgICAgLy8gQSBkZWxpdmVyeSBpcyBzdGlsbCBoeWRyYXRpbmcsIG9yIGlzIGNvbW1pdHRlZCBidXQgcGFya2VkIGJlaGluZCBpdHNcbiAgICAgIC8vIGRlZmVycmFsICh3aG9zZSByZXNvbHZlIHJ1bnMgb24gYSBkZXRhY2hlZCB0aW1lciwgbm90IHRoaXMgcXVldWUpLlxuICAgICAgLy8gRWl0aGVyIHdheTogbGV0IHRoZSBxdWV1ZSBkcmFpbiwgdGhlbiByZS1jaGVjayBhIHRpbWVyIHRpY2sgbGF0ZXIuXG4gICAgICBjdHgucHJvbWlzZVF1ZXVlLnRoZW4oKCkgPT4ge1xuICAgICAgICBzZXRUaW1lb3V0KGNoZWNrLCAwKTtcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBmbigpO1xuICAgIH1cbiAgfTtcbiAgc2V0VGltZW91dChjaGVjaywgMCk7XG59XG5cbi8qKiBTY2hlZHVsZSBhIGdlbmVyYXRpb24tZ3VhcmRlZCBzdXNwZW5zaW9uIGFmdGVyIGRlbGl2ZXJpZXMgc2V0dGxlLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNjaGVkdWxlV29ya2Zsb3dTdXNwZW5zaW9uKFxuICBjdHg6IFdvcmtmbG93T3JjaGVzdHJhdG9yQ29udGV4dFxuKTogdm9pZCB7XG4gIGNvbnN0IGdlbmVyYXRpb24gPSBjdHguc3VzcGVuc2lvbkdlbmVyYXRpb247XG4gIHNjaGVkdWxlV2hlbklkbGUoY3R4LCAoKSA9PiB7XG4gICAgaWYgKGdlbmVyYXRpb24gIT09IGN0eC5zdXNwZW5zaW9uR2VuZXJhdGlvbikgcmV0dXJuO1xuICAgIGN0eC5vbldvcmtmbG93RXJyb3IoXG4gICAgICBuZXcgV29ya2Zsb3dTdXNwZW5zaW9uKGN0eC5pbnZvY2F0aW9uc1F1ZXVlLCBjdHguZ2xvYmFsVGhpcylcbiAgICApO1xuICB9KTtcbn1cbiJdfQ==
|