@workflow/core 5.0.0-beta.42 → 5.0.0-beta.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/capabilities.d.ts +4 -4
- package/dist/capabilities.js +5 -5
- package/dist/capture-stack.d.ts +1 -1
- package/dist/capture-stack.js +2 -2
- package/dist/class-serialization.d.ts +8 -8
- package/dist/class-serialization.js +9 -9
- package/dist/classify-error.js +5 -5
- package/dist/context-violation-error.d.ts +5 -5
- package/dist/context-violation-error.d.ts.map +1 -1
- package/dist/context-violation-error.js +5 -5
- package/dist/create-hook.d.ts +10 -6
- package/dist/create-hook.d.ts.map +1 -1
- package/dist/create-hook.js +1 -1
- package/dist/define-hook.js +2 -2
- package/dist/describe-error.d.ts +7 -7
- package/dist/describe-error.js +8 -8
- package/dist/encryption.d.ts +5 -5
- package/dist/encryption.js +7 -7
- package/dist/events-consumer.d.ts +19 -7
- package/dist/events-consumer.d.ts.map +1 -1
- package/dist/events-consumer.js +33 -12
- package/dist/flushable-stream.d.ts +4 -4
- package/dist/flushable-stream.js +12 -12
- package/dist/global.d.ts +1 -1
- package/dist/global.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/log-format.d.ts +2 -2
- package/dist/log-format.js +5 -5
- package/dist/logger.js +4 -4
- package/dist/private.d.ts +39 -64
- package/dist/private.d.ts.map +1 -1
- package/dist/private.js +294 -48
- 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 +46 -19
- package/dist/runtime/constants.d.ts.map +1 -1
- package/dist/runtime/constants.js +76 -38
- package/dist/runtime/count-step-started-events.d.ts +7 -7
- package/dist/runtime/count-step-started-events.js +4 -4
- package/dist/runtime/deployment-guard.d.ts +7 -7
- package/dist/runtime/deployment-guard.js +8 -8
- package/dist/runtime/get-port-lazy.d.ts +2 -2
- package/dist/runtime/get-port-lazy.d.ts.map +1 -1
- package/dist/runtime/get-port-lazy.js +37 -30
- package/dist/runtime/get-world-lazy.d.ts +2 -2
- package/dist/runtime/get-world-lazy.js +3 -3
- package/dist/runtime/helpers.d.ts +18 -18
- package/dist/runtime/helpers.js +27 -27
- package/dist/runtime/quickjs-entrypoint.d.ts +23 -10
- package/dist/runtime/quickjs-entrypoint.d.ts.map +1 -1
- package/dist/runtime/quickjs-entrypoint.js +200 -81
- package/dist/runtime/quickjs-runtime.d.ts +31 -15
- package/dist/runtime/quickjs-runtime.d.ts.map +1 -1
- package/dist/runtime/quickjs-runtime.js +126 -77
- package/dist/runtime/quickjs-serde.d.ts +10 -10
- package/dist/runtime/quickjs-serde.js +20 -20
- package/dist/runtime/replay-budget.d.ts +4 -4
- package/dist/runtime/replay-budget.js +5 -5
- package/dist/runtime/replay-recovery-reporter.d.ts +1 -1
- package/dist/runtime/replay-recovery-reporter.js +2 -2
- package/dist/runtime/resume-hook.d.ts +2 -2
- package/dist/runtime/resume-hook.js +27 -27
- package/dist/runtime/resume-latency.d.ts +25 -25
- package/dist/runtime/resume-latency.d.ts.map +1 -1
- package/dist/runtime/resume-latency.js +4 -4
- package/dist/runtime/run-id-time.d.ts +2 -2
- package/dist/runtime/run-id-time.js +5 -5
- package/dist/runtime/run.d.ts +21 -4
- package/dist/runtime/run.d.ts.map +1 -1
- package/dist/runtime/run.js +154 -35
- package/dist/runtime/runs.d.ts +4 -4
- package/dist/runtime/runs.js +2 -2
- package/dist/runtime/start.d.ts +3 -3
- package/dist/runtime/start.d.ts.map +1 -1
- package/dist/runtime/start.js +27 -23
- package/dist/runtime/step-executor.d.ts +59 -11
- package/dist/runtime/step-executor.d.ts.map +1 -1
- package/dist/runtime/step-executor.js +116 -42
- package/dist/runtime/step-latency.d.ts +20 -14
- package/dist/runtime/step-latency.d.ts.map +1 -1
- package/dist/runtime/step-latency.js +13 -11
- package/dist/runtime/step-ownership.d.ts +6 -6
- package/dist/runtime/step-ownership.js +8 -8
- package/dist/runtime/step-single-flight.d.ts +1 -1
- package/dist/runtime/step-single-flight.d.ts.map +1 -1
- package/dist/runtime/step-single-flight.js +17 -11
- package/dist/runtime/suspension-handler.d.ts +99 -7
- package/dist/runtime/suspension-handler.d.ts.map +1 -1
- package/dist/runtime/suspension-handler.js +678 -57
- 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 +417 -213
- package/dist/sealed-box.d.ts +7 -7
- package/dist/sealed-box.js +15 -15
- package/dist/serialization/client.js +2 -2
- package/dist/serialization/codec-devalue-vm.d.ts +1 -1
- package/dist/serialization/codec-devalue-vm.js +4 -4
- package/dist/serialization/codec-devalue.d.ts +1 -1
- package/dist/serialization/codec-devalue.js +2 -2
- package/dist/serialization/codec.d.ts +4 -4
- package/dist/serialization/codec.js +2 -2
- package/dist/serialization/compression.d.ts +12 -11
- package/dist/serialization/compression.d.ts.map +1 -1
- package/dist/serialization/compression.js +16 -15
- package/dist/serialization/encryption.d.ts +7 -7
- package/dist/serialization/encryption.d.ts.map +1 -1
- package/dist/serialization/encryption.js +8 -8
- package/dist/serialization/errors.js +2 -2
- package/dist/serialization/format.d.ts +6 -6
- package/dist/serialization/format.js +7 -7
- package/dist/serialization/hardened.d.ts +18 -18
- package/dist/serialization/hardened.d.ts.map +1 -1
- package/dist/serialization/hardened.js +41 -32
- package/dist/serialization/index.d.ts +1 -1
- package/dist/serialization/index.js +2 -2
- package/dist/serialization/reducers/class-vm.d.ts +1 -1
- package/dist/serialization/reducers/class-vm.js +2 -2
- package/dist/serialization/reducers/class.js +2 -2
- package/dist/serialization/reducers/common-vm.js +12 -12
- package/dist/serialization/reducers/common.js +12 -12
- package/dist/serialization/reducers/step-function-vm.d.ts +1 -1
- package/dist/serialization/reducers/step-function-vm.js +2 -2
- package/dist/serialization/reducers/step-function.js +2 -2
- package/dist/serialization/step.js +2 -2
- package/dist/serialization/types.d.ts +5 -5
- package/dist/serialization/types.js +2 -2
- package/dist/serialization/workflow-vm.d.ts +1 -1
- package/dist/serialization/workflow-vm.d.ts.map +1 -1
- package/dist/serialization/workflow-vm.js +13 -10
- package/dist/serialization-format.d.ts +11 -11
- package/dist/serialization-format.d.ts.map +1 -1
- package/dist/serialization-format.js +29 -23
- package/dist/serialization.d.ts +20 -12
- package/dist/serialization.d.ts.map +1 -1
- package/dist/serialization.js +141 -99
- package/dist/set-attributes.js +2 -2
- package/dist/source-map.d.ts +1 -1
- package/dist/source-map.d.ts.map +1 -1
- package/dist/source-map.js +18 -12
- package/dist/step/context-storage.d.ts +5 -5
- package/dist/step/context-storage.js +1 -1
- package/dist/step/writable-stream.d.ts +3 -3
- package/dist/step/writable-stream.js +7 -7
- package/dist/step.js +12 -12
- package/dist/symbols.d.ts +2 -2
- package/dist/symbols.js +3 -3
- package/dist/telemetry/semantic-conventions.d.ts +21 -13
- package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
- package/dist/telemetry/semantic-conventions.js +21 -15
- package/dist/telemetry.d.ts +9 -3
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +40 -10
- package/dist/test-support/orchestrator-context.d.ts.map +1 -1
- package/dist/test-support/orchestrator-context.js +12 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +2 -2
- package/dist/vm/index.js +4 -4
- package/dist/vm/script-cache.d.ts.map +1 -1
- package/dist/vm/script-cache.js +23 -17
- package/dist/vm/uint8array-base64.js +1 -1
- package/dist/workflow/abort-controller.d.ts +1 -1
- package/dist/workflow/abort-controller.js +12 -12
- package/dist/workflow/create-hook.js +3 -3
- package/dist/workflow/get-workflow-metadata.js +2 -2
- package/dist/workflow/hook.js +18 -18
- 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 +36 -14
- 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 +37 -37
- 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 +68 -39
- 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 +84 -28
- 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
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { globalSingleton } from '@workflow/utils';
|
|
1
2
|
import { envNumber } from '@workflow/world';
|
|
2
3
|
import { runtimeLogger } from '../logger.js';
|
|
3
4
|
// Maximum number of queue delivery attempts before the handler gives up and
|
|
@@ -9,15 +10,15 @@ import { runtimeLogger } from '../logger.js';
|
|
|
9
10
|
// `retry-after` the handler returns (see world-vercel
|
|
10
11
|
// `getHandlerErrorRetryAfterSeconds`) fed through VQS `calculateBackoffDelay`.
|
|
11
12
|
// VQS uses our value for the first 32 attempts (clamped to [5s, 900s]) then
|
|
12
|
-
// applies its own exponential growth
|
|
13
|
+
// applies its own exponential growth, every hop hard-capped at the SQS limit
|
|
13
14
|
// of 900s. With the backoff ramping toward that 900s ceiling (reached by
|
|
14
15
|
// ~delivery 11), 48 attempts span roughly 9–10 hours of wall-clock (~35,000s),
|
|
15
16
|
// comfortably under the 24-hour message-visibility limit so the failure path
|
|
16
17
|
// runs before the message expires. (A flatter, low-capped backoff exhausts the
|
|
17
18
|
// budget in only a few hours, failing otherwise-healthy runs during a transient
|
|
18
19
|
// backend outage; conversely, spanning the full 24h window would require a
|
|
19
|
-
// substantially higher cap here, not a higher per-hop ceiling
|
|
20
|
-
// every hop at 900s.)
|
|
20
|
+
// substantially higher cap here, not a higher per-hop ceiling, since VQS
|
|
21
|
+
// clamps every hop at 900s.)
|
|
21
22
|
export const MAX_QUEUE_DELIVERIES = 48;
|
|
22
23
|
/**
|
|
23
24
|
* Effective max queue deliveries. Override via `WORKFLOW_MAX_QUEUE_DELIVERIES`.
|
|
@@ -37,7 +38,7 @@ export function getMaxQueueDeliveries() {
|
|
|
37
38
|
/**
|
|
38
39
|
* Default maximum time allowed for the *replay* portion of a single workflow
|
|
39
40
|
* handler invocation (in ms). This budget only covers deterministic-replay
|
|
40
|
-
* and workflow-VM execution between step boundaries
|
|
41
|
+
* and workflow-VM execution between step boundaries. Inline step bodies
|
|
41
42
|
* (`"use step"` functions invoked via `executeStep`) do NOT count against
|
|
42
43
|
* it. Step bodies are bounded separately by the platform's function
|
|
43
44
|
* `maxDuration` (e.g. 800s on Vercel Pro Fluid) and `NO_INLINE_REPLAY_AFTER_MS`.
|
|
@@ -48,7 +49,7 @@ export function getMaxQueueDeliveries() {
|
|
|
48
49
|
* `RUN_ERROR_CODES.REPLAY_TIMEOUT`.
|
|
49
50
|
*
|
|
50
51
|
* Note that on Vercel Hobby (standard functions), the platform `maxDuration`
|
|
51
|
-
* is 60s
|
|
52
|
+
* is 60s, well below this budget, so the platform SIGTERM will fire first
|
|
52
53
|
* and the queue will re-deliver until the visibility window expires. With
|
|
53
54
|
* Fluid Compute on Hobby the per-function ceiling rises to 300s, still
|
|
54
55
|
* under the default budget.
|
|
@@ -67,11 +68,19 @@ export const MIN_REPLAY_TIMEOUT_MS = 30_000;
|
|
|
67
68
|
export const MAX_REPLAY_TIMEOUT_MS = 780_000;
|
|
68
69
|
// Track which raw env var values we've already warned about so the warning
|
|
69
70
|
// log only fires once per process (the function may be called many times).
|
|
70
|
-
|
|
71
|
+
//
|
|
72
|
+
// On `globalThis` rather than at module scope so "once per process" survives
|
|
73
|
+
// bundling: this package is compiled into the host application's server build
|
|
74
|
+
// once per bundler layer, and per-copy sets warn once per layer instead.
|
|
75
|
+
const warned = globalSingleton('@workflow/core//envWarnings', 1, () => ({
|
|
76
|
+
replayTimeoutValues: new Set(),
|
|
77
|
+
maxInlineStepsValues: new Set(),
|
|
78
|
+
maxEventsValues: new Set(),
|
|
79
|
+
}));
|
|
71
80
|
function warnOnce(raw, message, data) {
|
|
72
|
-
if (
|
|
81
|
+
if (warned.replayTimeoutValues.has(raw))
|
|
73
82
|
return;
|
|
74
|
-
|
|
83
|
+
warned.replayTimeoutValues.add(raw);
|
|
75
84
|
runtimeLogger.warn(message, data);
|
|
76
85
|
}
|
|
77
86
|
/**
|
|
@@ -79,7 +88,7 @@ function warnOnce(raw, message, data) {
|
|
|
79
88
|
*
|
|
80
89
|
* Reads `process.env.WORKFLOW_REPLAY_TIMEOUT_MS` lazily so tests and
|
|
81
90
|
* deployments can override per invocation. Invalid / out-of-range values
|
|
82
|
-
* fall back to a safe value (no throw
|
|
91
|
+
* fall back to a safe value (no throw: the env var is an escape hatch,
|
|
83
92
|
* not a hard requirement) and emit a one-time warning so misconfiguration
|
|
84
93
|
* is observable.
|
|
85
94
|
*/
|
|
@@ -111,13 +120,13 @@ export function getReplayTimeoutMs() {
|
|
|
111
120
|
return parsed;
|
|
112
121
|
}
|
|
113
122
|
/**
|
|
114
|
-
* Reset the warn-once cache. Test-only
|
|
123
|
+
* Reset the warn-once cache. Test-only: exported so unit tests can
|
|
115
124
|
* exercise the warn path repeatedly without sharing state.
|
|
116
125
|
*
|
|
117
126
|
* @internal
|
|
118
127
|
*/
|
|
119
128
|
export function _resetReplayTimeoutWarnCacheForTests() {
|
|
120
|
-
|
|
129
|
+
warned.replayTimeoutValues.clear();
|
|
121
130
|
}
|
|
122
131
|
// Number of queue delivery attempts to allow before permanently failing a run
|
|
123
132
|
// due to a replay timeout. On attempts 1 through this value, the timeout
|
|
@@ -134,8 +143,8 @@ export function getReplayTimeoutMaxRetries() {
|
|
|
134
143
|
/**
|
|
135
144
|
* Default maximum number of steps the owned-inline path runs inline (in
|
|
136
145
|
* parallel) per suspension. The rest are queued to background handlers. Each
|
|
137
|
-
* inline step is created lazily
|
|
138
|
-
* `step_started` that `executeStep` sends
|
|
146
|
+
* inline step is created lazily (its `step_created` is folded into the
|
|
147
|
+
* `step_started` that `executeStep` sends), so inlining N steps saves N queue
|
|
139
148
|
* round-trips for a `Promise.all`-style fan-out. `1` reproduces the
|
|
140
149
|
* single-inline-step behavior exactly (useful kill-switch).
|
|
141
150
|
*
|
|
@@ -150,14 +159,12 @@ export const MIN_MAX_INLINE_STEPS = 1;
|
|
|
150
159
|
* within one function invocation, so this caps memory/CPU fan-out per handler.
|
|
151
160
|
*/
|
|
152
161
|
export const MAX_MAX_INLINE_STEPS = 16;
|
|
153
|
-
// Warn-once cache for WORKFLOW_MAX_INLINE_STEPS, keyed by raw env value.
|
|
154
|
-
const warnedMaxInlineStepsValues = new Set();
|
|
155
162
|
/**
|
|
156
163
|
* Resolve the effective max number of inline steps for the current process.
|
|
157
164
|
*
|
|
158
165
|
* Reads `process.env.WORKFLOW_MAX_INLINE_STEPS` lazily so tests and
|
|
159
166
|
* deployments can override per invocation. Invalid / out-of-range values fall
|
|
160
|
-
* back to a safe value (no throw
|
|
167
|
+
* back to a safe value (no throw: the env var is an escape hatch) and emit a
|
|
161
168
|
* one-time warning so misconfiguration is observable.
|
|
162
169
|
*/
|
|
163
170
|
export function getMaxInlineSteps() {
|
|
@@ -166,8 +173,8 @@ export function getMaxInlineSteps() {
|
|
|
166
173
|
return MAX_INLINE_STEPS;
|
|
167
174
|
const parsed = Number(raw);
|
|
168
175
|
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
169
|
-
if (!
|
|
170
|
-
|
|
176
|
+
if (!warned.maxInlineStepsValues.has(raw)) {
|
|
177
|
+
warned.maxInlineStepsValues.add(raw);
|
|
171
178
|
runtimeLogger.warn('Ignoring WORKFLOW_MAX_INLINE_STEPS: not a positive integer; using default', { raw, defaultValue: MAX_INLINE_STEPS });
|
|
172
179
|
}
|
|
173
180
|
return MAX_INLINE_STEPS;
|
|
@@ -175,8 +182,8 @@ export function getMaxInlineSteps() {
|
|
|
175
182
|
if (parsed < MIN_MAX_INLINE_STEPS)
|
|
176
183
|
return MIN_MAX_INLINE_STEPS;
|
|
177
184
|
if (parsed > MAX_MAX_INLINE_STEPS) {
|
|
178
|
-
if (!
|
|
179
|
-
|
|
185
|
+
if (!warned.maxInlineStepsValues.has(raw)) {
|
|
186
|
+
warned.maxInlineStepsValues.add(raw);
|
|
180
187
|
runtimeLogger.warn('WORKFLOW_MAX_INLINE_STEPS above maximum; clamped', {
|
|
181
188
|
raw,
|
|
182
189
|
clampedValue: MAX_MAX_INLINE_STEPS,
|
|
@@ -214,7 +221,7 @@ export const MAX_RESILIENT_STEP_INPUT_BYTES = 128 * 1024;
|
|
|
214
221
|
* **Off by default.** Enable via `WORKFLOW_RESILIENT_STEP_DISPATCH=1`.
|
|
215
222
|
*
|
|
216
223
|
* The queue publish races the create's verdict, and a create can come back
|
|
217
|
-
* refused
|
|
224
|
+
* refused: as a duplicate this replay should stop pursuing, or as a stale
|
|
218
225
|
* write on a World that refuses rather than reports. Either way the message
|
|
219
226
|
* carrying the payload is already out, so the consumer can materialize a step
|
|
220
227
|
* whose create was refused, and nothing orders the verdict before the
|
|
@@ -224,7 +231,38 @@ export const MAX_RESILIENT_STEP_INPUT_BYTES = 128 * 1024;
|
|
|
224
231
|
export function isResilientStepDispatchEnabled() {
|
|
225
232
|
return process.env.WORKFLOW_RESILIENT_STEP_DISPATCH === '1';
|
|
226
233
|
}
|
|
227
|
-
|
|
234
|
+
/**
|
|
235
|
+
* Whether batched event transitions are enabled: the suspension handler folds
|
|
236
|
+
* a clean fan-out's `step_created` + `wait_created` writes into one
|
|
237
|
+
* `world.events.createBatch` call (one durable write, per-event outcomes)
|
|
238
|
+
* instead of one write per event. Only engages when the World implements the
|
|
239
|
+
* optional `events.createBatch` AND the run is on slot identity
|
|
240
|
+
* (specVersion >= 6) AND the suspension carries no attribute/hook writes and
|
|
241
|
+
* no resilient step dispatch. Everything else keeps the single-event path
|
|
242
|
+
* byte-for-byte.
|
|
243
|
+
*
|
|
244
|
+
* Reads `process.env.WORKFLOW_BATCH_TRANSITIONS` lazily. Default **ON**;
|
|
245
|
+
* disabled only by an explicit `'0'` / `'false'` (case-insensitive), the
|
|
246
|
+
* operator escape hatch that restores the exact prior one-write-per-event
|
|
247
|
+
* path, mirroring `WORKFLOW_TURBO`'s kill-switch shape.
|
|
248
|
+
*/
|
|
249
|
+
export function isBatchTransitionsEnabled() {
|
|
250
|
+
const raw = process.env.WORKFLOW_BATCH_TRANSITIONS;
|
|
251
|
+
if (raw === undefined || raw === '')
|
|
252
|
+
return true;
|
|
253
|
+
return !(raw === '0' || raw.toLowerCase() === 'false');
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Ceiling on events per `createBatch` call from the batched fan-out fold.
|
|
257
|
+
* Mirrors the server's transaction budgets with a comfortable margin: each
|
|
258
|
+
* fan-out event costs 2 transaction items server-side (entity + event row)
|
|
259
|
+
* against the 100-item DynamoDB cap, and inline payloads count against a
|
|
260
|
+
* 768 KB byte budget, so 32 events stays well under both, and a fan-out larger
|
|
261
|
+
* than this commits in successive batches (split batches lose
|
|
262
|
+
* cross-batch atomicity, which is exactly today's per-event-write crash
|
|
263
|
+
* surface, and every batch still converges on retry via per-event 409s).
|
|
264
|
+
*/
|
|
265
|
+
export const MAX_BATCH_FANOUT_EVENTS = 32;
|
|
228
266
|
/**
|
|
229
267
|
* Optional client-side override for the server-supplied per-run event ceiling.
|
|
230
268
|
* When set to a positive integer, the runtime clamps the server's limit *down*
|
|
@@ -233,7 +271,7 @@ const warnedMaxEventsValues = new Set();
|
|
|
233
271
|
*
|
|
234
272
|
* Reads `process.env.WORKFLOW_MAX_EVENTS_OVERRIDE` lazily so tests and
|
|
235
273
|
* deployments can override per invocation. Invalid values fall back to unset
|
|
236
|
-
* (no throw
|
|
274
|
+
* (no throw: the env var is an escape hatch) and emit a one-time warning.
|
|
237
275
|
*/
|
|
238
276
|
export function getMaxEventsOverride() {
|
|
239
277
|
const raw = process.env.WORKFLOW_MAX_EVENTS_OVERRIDE;
|
|
@@ -241,8 +279,8 @@ export function getMaxEventsOverride() {
|
|
|
241
279
|
return undefined;
|
|
242
280
|
const parsed = Number(raw);
|
|
243
281
|
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
244
|
-
if (!
|
|
245
|
-
|
|
282
|
+
if (!warned.maxEventsValues.has(raw)) {
|
|
283
|
+
warned.maxEventsValues.add(raw);
|
|
246
284
|
runtimeLogger.warn('Ignoring WORKFLOW_MAX_EVENTS_OVERRIDE: not a positive integer; using server limit', { raw });
|
|
247
285
|
}
|
|
248
286
|
return undefined;
|
|
@@ -256,7 +294,7 @@ export function getMaxEventsOverride() {
|
|
|
256
294
|
* `step_started` only before the terminal write.
|
|
257
295
|
*
|
|
258
296
|
* This can run a step body more than once when handlers race for the same
|
|
259
|
-
* step's create-claim
|
|
297
|
+
* step's create-claim: both run the body before one wins. That is unsafe for
|
|
260
298
|
* steps with non-idempotent side effects; in particular, two concurrent runs
|
|
261
299
|
* of a step that writes to the workflow stream (e.g. an AI agent streaming
|
|
262
300
|
* tokens) can interleave and corrupt the stream data. So the optimization is
|
|
@@ -291,7 +329,7 @@ export function isOptimisticInlineStartExplicitlyDisabled() {
|
|
|
291
329
|
* the first invocation* of a run (detected by the entrypoint via `runInput`
|
|
292
330
|
* presence + `metadata.attempt === 1`): it backgrounds the `run_started` event
|
|
293
331
|
* creation, skips the initial event-log load (nothing has been written yet),
|
|
294
|
-
* and forces optimistic inline step start for that invocation
|
|
332
|
+
* and forces optimistic inline step start for that invocation, independent of
|
|
295
333
|
* `WORKFLOW_OPTIMISTIC_INLINE_START`.
|
|
296
334
|
*
|
|
297
335
|
* Forcing optimistic start is safe here because the first delivery has no
|
|
@@ -314,7 +352,7 @@ export function isTurboEnabled() {
|
|
|
314
352
|
* enabled (default ON). When on, the engine hydrates a VM with the
|
|
315
353
|
* workflow bundle once per function instance, snapshots it, and starts
|
|
316
354
|
* every invocation by restoring the snapshot instead of re-evaluating
|
|
317
|
-
* the bundle
|
|
355
|
+
* the bundle, skipping the dominant share of VM startup (measured
|
|
318
356
|
* ~77ms → ~3ms to first suspension for a 1.3MB bundle). Bundles whose
|
|
319
357
|
* module scope consumes randomness, reads the clock, or replaces a
|
|
320
358
|
* serialization intrinsic are detected at hydrate time and
|
|
@@ -349,12 +387,12 @@ export function isVmRetentionEnabled() {
|
|
|
349
387
|
* Whether inline step ownership is enabled (default ON). When on, the lazy
|
|
350
388
|
* `step_started` that creates an inline step records the owning queue
|
|
351
389
|
* message ID, and wake replays that observe an actively-owned step enqueue a
|
|
352
|
-
* *delayed backstop* message instead of immediately requeueing it
|
|
390
|
+
* *delayed backstop* message instead of immediately requeueing it, fixing
|
|
353
391
|
* duplicate inline step execution when a hook/wait wakes a run mid-step
|
|
354
392
|
* (vercel/workflow#2780).
|
|
355
393
|
*
|
|
356
394
|
* `WORKFLOW_INLINE_OWNERSHIP=0` (or `false`) is the kill switch: dispatch
|
|
357
|
-
* reverts to the unconditional immediate requeue. Stamping is unaffected
|
|
395
|
+
* reverts to the unconditional immediate requeue. Stamping is unaffected:
|
|
358
396
|
* the recorded ownerMessageId is inert data when the switch is off.
|
|
359
397
|
*/
|
|
360
398
|
export function isInlineOwnershipEnabled() {
|
|
@@ -371,16 +409,16 @@ export function isInlineOwnershipEnabled() {
|
|
|
371
409
|
* immediately; past it, they enqueue immediately (today's behavior).
|
|
372
410
|
*
|
|
373
411
|
* Why a fixed 860 and not a value derived from the function's `maxDuration`:
|
|
374
|
-
* neither runtime nor build time can see the resolved value
|
|
412
|
+
* neither runtime nor build time can see the resolved value: builders emit
|
|
375
413
|
* `maxDuration: 'max'`, which the platform resolves per-plan at deploy, and
|
|
376
414
|
* no env var or request-context deadline API exposes the result. The bound
|
|
377
415
|
* comes from a platform rule instead: durations above 800s require explicit
|
|
378
416
|
* per-function numeric config, so a builder-emitted `'max'` resolves to at
|
|
379
|
-
* most 800s
|
|
417
|
+
* most 800s, and 860s therefore dominates any workflow route's invocation
|
|
380
418
|
* lifetime plus scheduling slack. Revisit when that ceiling moves (the
|
|
381
419
|
* 30-minute duration beta becoming reachable via `'max'` would invalidate
|
|
382
420
|
* the bound). Worlds without an invocation kill bound (world-local,
|
|
383
|
-
* self-hosted) get no death proof from any constant
|
|
421
|
+
* self-hosted) get no death proof from any constant. There the in-process
|
|
384
422
|
* single-flight layer (step-single-flight.ts) is what makes a backstop
|
|
385
423
|
* firing mid-step harmless.
|
|
386
424
|
*
|
|
@@ -393,13 +431,13 @@ export function isInlineOwnershipEnabled() {
|
|
|
393
431
|
export const INLINE_OWNERSHIP_LEASE_SECONDS = 860;
|
|
394
432
|
/**
|
|
395
433
|
* Upper bound for the lease env override. 900s is the queue's maximum
|
|
396
|
-
* per-message delay (SQS cap)
|
|
434
|
+
* per-message delay (SQS cap). A longer lease would need delay chaining
|
|
397
435
|
* like long waits use; clamp instead so one delayed message always suffices.
|
|
398
436
|
*/
|
|
399
437
|
export const MAX_INLINE_OWNERSHIP_LEASE_SECONDS = 900;
|
|
400
438
|
/**
|
|
401
439
|
* Effective inline-ownership lease. Override via
|
|
402
|
-
* `WORKFLOW_INLINE_OWNERSHIP_LEASE_SECONDS
|
|
440
|
+
* `WORKFLOW_INLINE_OWNERSHIP_LEASE_SECONDS`, e.g. raise it on self-hosted
|
|
403
441
|
* multi-instance worlds with long-running steps to widen the window in which
|
|
404
442
|
* a live owner is protected from a concurrent backstop execution.
|
|
405
443
|
*/
|
|
@@ -434,9 +472,9 @@ export function getPreconditionMaxInProcessRestarts() {
|
|
|
434
472
|
// The in-process budget above is per-invocation, and a re-invocation that
|
|
435
473
|
// enqueues a fresh message also restarts the queue's delivery count, so without
|
|
436
474
|
// a counter carried on the message a permanently fenced run has no run-level
|
|
437
|
-
// bound at all. It can stay fenced without any permanent fault
|
|
475
|
+
// bound at all. It can stay fenced without any permanent fault (a full reload
|
|
438
476
|
// is not atomic across pages, so a busy run can acquire a new hole on every
|
|
439
|
-
// reload
|
|
477
|
+
// reload), so the chain is counted and the run fails once this many
|
|
440
478
|
// re-invocations have been spent on stale-snapshot rejections.
|
|
441
479
|
export const PRECONDITION_MAX_REINVOCATIONS = 5;
|
|
442
480
|
/**
|
|
@@ -470,4 +508,4 @@ export const DEPLOYMENT_MISMATCH_MAX_RETRIES = 3;
|
|
|
470
508
|
export function getDeploymentMismatchMaxRetries() {
|
|
471
509
|
return envNumber('WORKFLOW_DEPLOYMENT_MISMATCH_MAX_RETRIES', DEPLOYMENT_MISMATCH_MAX_RETRIES, { integer: true, min: 0 });
|
|
472
510
|
}
|
|
473
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bnRpbWUvY29uc3RhbnRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUM1QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBRTdDLDRFQUE0RTtBQUM1RSw0RUFBNEU7QUFDNUUseUVBQXlFO0FBQ3pFLG9EQUFvRDtBQUNwRCxFQUFFO0FBQ0YsK0VBQStFO0FBQy9FLHNEQUFzRDtBQUN0RCwrRUFBK0U7QUFDL0UsNEVBQTRFO0FBQzVFLDhFQUE4RTtBQUM5RSx5RUFBeUU7QUFDekUsK0VBQStFO0FBQy9FLDZFQUE2RTtBQUM3RSwrRUFBK0U7QUFDL0UsZ0ZBQWdGO0FBQ2hGLDJFQUEyRTtBQUMzRSwyRUFBMkU7QUFDM0Usc0JBQXNCO0FBQ3RCLE1BQU0sQ0FBQyxNQUFNLG9CQUFvQixHQUFHLEVBQUUsQ0FBQztBQUV2Qzs7R0FFRztBQUNILE1BQU0sVUFBVSxxQkFBcUI7SUFDbkMsd0VBQXdFO0lBQ3hFLDBFQUEwRTtJQUMxRSw4RUFBOEU7SUFDOUUseUVBQXlFO0lBQ3pFLDRFQUE0RTtJQUM1RSxPQUFPLFNBQVMsQ0FBQywrQkFBK0IsRUFBRSxvQkFBb0IsRUFBRTtRQUN0RSxPQUFPLEVBQUUsSUFBSTtRQUNiLEdBQUcsRUFBRSxDQUFDO1FBQ04sR0FBRyxFQUFFLG9CQUFvQjtLQUMxQixDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXFCRztBQUNILE1BQU0sQ0FBQyxNQUFNLGlCQUFpQixHQUFHLE9BQU8sQ0FBQztBQUV6QywyREFBMkQ7QUFDM0QsTUFBTSxDQUFDLE1BQU0scUJBQXFCLEdBQUcsTUFBTSxDQUFDO0FBRTVDOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsTUFBTSxxQkFBcUIsR0FBRyxPQUFPLENBQUM7QUFFN0Ms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QUFDSixDQUFDO0FBRUQsMEVBQTBFO0FBQzFFLGdGQUFnRjtBQUNoRiw2RUFBNkU7QUFDN0UsK0VBQStFO0FBQy9FLDRFQUE0RTtBQUM1RSxvRUFBb0U7QUFDcEUsK0RBQStEO0FBQy9ELE1BQU0sQ0FBQyxNQUFNLDhCQUE4QixHQUFHLENBQUMsQ0FBQztBQUVoRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsK0JBQStCO0lBQzdDLE9BQU8sU0FBUyxDQUNkLHlDQUF5QyxFQUN6Qyw4QkFBOEIsRUFDOUIsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQ2xCLENBQUM7QUFDSixDQUFDO0FBRUQsNkVBQTZFO0FBQzdFLDRFQUE0RTtBQUM1RSwrRUFBK0U7QUFDL0UsMkVBQTJFO0FBQzNFLE1BQU0sQ0FBQyxNQUFNLG1DQUFtQyxHQUFHLENBQUMsQ0FBQztBQUVyRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsbUNBQW1DO0lBQ2pELE9BQU8sU0FBUyxDQUNkLDhDQUE4QyxFQUM5QyxtQ0FBbUMsRUFDbkMsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQ2xCLENBQUM7QUFDSixDQUFDO0FBRUQsOEVBQThFO0FBQzlFLCtFQUErRTtBQUMvRSw0REFBNEQ7QUFDNUQsTUFBTSxDQUFDLE1BQU0sK0JBQStCLEdBQUcsQ0FBQyxDQUFDO0FBRWpEOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUsK0JBQStCO0lBQzdDLE9BQU8sU0FBUyxDQUNkLDBDQUEwQyxFQUMxQywrQkFBK0IsRUFDL0IsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsQ0FDMUIsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBlbnZOdW1iZXIgfSBmcm9tICdAd29ya2Zsb3cvd29ybGQnO1xuaW1wb3J0IHsgcnVudGltZUxvZ2dlciB9IGZyb20gJy4uL2xvZ2dlci5qcyc7XG5cbi8vIE1heGltdW0gbnVtYmVyIG9mIHF1ZXVlIGRlbGl2ZXJ5IGF0dGVtcHRzIGJlZm9yZSB0aGUgaGFuZGxlciBnaXZlcyB1cCBhbmRcbi8vIGdyYWNlZnVsbHkgZmFpbHMgdGhlIHJ1bi9zdGVwLiBUaGlzIG11c3QgYmUgYm91bmRlZCB1bmRlciB0aGUgVlFTIG1lc3NhZ2Vcbi8vIG1heCB2aXNpYmlsaXR5IHdpbmRvdyAoMjQgaG91cnMpIHNvIHRoYXQgb3VyIGhhbmRsZXItc2lkZSBmYWlsdXJlIHBhdGhcbi8vIHJlbGlhYmx5IGV4ZWN1dGVzIGJlZm9yZSBWUVMgZXhwaXJlcyB0aGUgbWVzc2FnZS5cbi8vXG4vLyBUaGUgZWZmZWN0aXZlIHdhbGwtY2xvY2sgc3Vydml2YWwgZGVwZW5kcyBvbiB0aGUgcGVyLXJlZGVsaXZlcnkgYmFja29mZjogdGhlXG4vLyBgcmV0cnktYWZ0ZXJgIHRoZSBoYW5kbGVyIHJldHVybnMgKHNlZSB3b3JsZC12ZXJjZWxcbi8vIGBnZXRIYW5kbGVyRXJyb3JSZXRyeUFmdGVyU2Vjb25kc2ApIGZlZCB0aHJvdWdoIFZRUyBgY2FsY3VsYXRlQmFja29mZkRlbGF5YC5cbi8vIFZRUyB1c2VzIG91ciB2YWx1ZSBmb3IgdGhlIGZpcnN0IDMyIGF0dGVtcHRzIChjbGFtcGVkIHRvIFs1cywgOTAwc10pIHRoZW5cbi8vIGFwcGxpZXMgaXRzIG93biBleHBvbmVudGlhbCBncm93dGgg4oCUIGV2ZXJ5IGhvcCBoYXJkLWNhcHBlZCBhdCB0aGUgU1FTIGxpbWl0XG4vLyBvZiA5MDBzLiBXaXRoIHRoZSBiYWNrb2ZmIHJhbXBpbmcgdG93YXJkIHRoYXQgOTAwcyBjZWlsaW5nIChyZWFjaGVkIGJ5XG4vLyB+ZGVsaXZlcnkgMTEpLCA0OCBhdHRlbXB0cyBzcGFuIHJvdWdobHkgOeKAkzEwIGhvdXJzIG9mIHdhbGwtY2xvY2sgKH4zNSwwMDBzKSxcbi8vIGNvbWZvcnRhYmx5IHVuZGVyIHRoZSAyNC1ob3VyIG1lc3NhZ2UtdmlzaWJpbGl0eSBsaW1pdCBzbyB0aGUgZmFpbHVyZSBwYXRoXG4vLyBydW5zIGJlZm9yZSB0aGUgbWVzc2FnZSBleHBpcmVzLiAoQSBmbGF0dGVyLCBsb3ctY2FwcGVkIGJhY2tvZmYgZXhoYXVzdHMgdGhlXG4vLyBidWRnZXQgaW4gb25seSBhIGZldyBob3VycywgZmFpbGluZyBvdGhlcndpc2UtaGVhbHRoeSBydW5zIGR1cmluZyBhIHRyYW5zaWVudFxuLy8gYmFja2VuZCBvdXRhZ2U7IGNvbnZlcnNlbHksIHNwYW5uaW5nIHRoZSBmdWxsIDI0aCB3aW5kb3cgd291bGQgcmVxdWlyZSBhXG4vLyBzdWJzdGFudGlhbGx5IGhpZ2hlciBjYXAgaGVyZSwgbm90IGEgaGlnaGVyIHBlci1ob3AgY2VpbGluZyDigJQgVlFTIGNsYW1wc1xuLy8gZXZlcnkgaG9wIGF0IDkwMHMuKVxuZXhwb3J0IGNvbnN0IE1BWF9RVUVVRV9ERUxJVkVSSUVTID0gNDg7XG5cbi8qKlxuICogRWZmZWN0aXZlIG1heCBxdWV1ZSBkZWxpdmVyaWVzLiBPdmVycmlkZSB2aWEgYFdPUktGTE9XX01BWF9RVUVVRV9ERUxJVkVSSUVTYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldE1heFF1ZXVlRGVsaXZlcmllcygpOiBudW1iZXIge1xuICAvLyBPbmx5IGV2ZXIgbG93ZXIgdGhlIGRlbGl2ZXJ5IGJ1ZGdldC4gVGhlIGRlZmF1bHQgaXMgY2FsaWJyYXRlZCBzbyB0aGVcbiAgLy8gaGFuZGxlci1zaWRlIGZhaWx1cmUgcGF0aCBydW5zIGJlZm9yZSBWUVMgbWVzc2FnZS1yZXRlbnRpb24gZXhwaXJ5IChzZWVcbiAgLy8gTUFYX1FVRVVFX0RFTElWRVJJRVMgYWJvdmUpOyBhIGhpZ2hlciB2YWx1ZSB3b3VsZCBieXBhc3MgdGhhdCBpbnZhcmlhbnQgYW5kXG4gIC8vIGxldCBhIGJhZCBkZXBsb3ltZW50IHJlZGVsaXZlciB1bnRpbCBxdWV1ZSBleHBpcnkgaW5zdGVhZCBvZiByZWNvcmRpbmdcbiAgLy8gcnVuX2ZhaWwuIGBtYXhgIGNsYW1wcyBhIHRvby1oaWdoIG92ZXJyaWRlIGJhY2sgZG93biB0byB0aGUgc2FmZSBkZWZhdWx0LlxuICByZXR1cm4gZW52TnVtYmVyKCdXT1JLRkxPV19NQVhfUVVFVUVfREVMSVZFUklFUycsIE1BWF9RVUVVRV9ERUxJVkVSSUVTLCB7XG4gICAgaW50ZWdlcjogdHJ1ZSxcbiAgICBtaW46IDEsXG4gICAgbWF4OiBNQVhfUVVFVUVfREVMSVZFUklFUyxcbiAgfSk7XG59XG5cbi8qKlxuICogRGVmYXVsdCBtYXhpbXVtIHRpbWUgYWxsb3dlZCBmb3IgdGhlICpyZXBsYXkqIHBvcnRpb24gb2YgYSBzaW5nbGUgd29ya2Zsb3dcbiAqIGhhbmRsZXIgaW52b2NhdGlvbiAoaW4gbXMpLiBUaGlzIGJ1ZGdldCBvbmx5IGNvdmVycyBkZXRlcm1pbmlzdGljLXJlcGxheVxuICogYW5kIHdvcmtmbG93LVZNIGV4ZWN1dGlvbiBiZXR3ZWVuIHN0ZXAgYm91bmRhcmllcyDigJQgaW5saW5lIHN0ZXAgYm9kaWVzXG4gKiAoYFwidXNlIHN0ZXBcImAgZnVuY3Rpb25zIGludm9rZWQgdmlhIGBleGVjdXRlU3RlcGApIGRvIE5PVCBjb3VudCBhZ2FpbnN0XG4gKiBpdC4gU3RlcCBib2RpZXMgYXJlIGJvdW5kZWQgc2VwYXJhdGVseSBieSB0aGUgcGxhdGZvcm0ncyBmdW5jdGlvblxuICogYG1heER1cmF0aW9uYCAoZS5nLiA4MDBzIG9uIFZlcmNlbCBQcm8gRmx1aWQpIGFuZCBgTk9fSU5MSU5FX1JFUExBWV9BRlRFUl9NU2AuXG4gKlxuICogSWYgdGhlIG5vbi1zdGVwIChcInJlcGxheVwiKSB0aW1lIHdpdGhpbiBhIHNpbmdsZSBpbnZvY2F0aW9uIGV4Y2VlZHMgdGhpc1xuICogYnVkZ2V0LCB0aGUgaGFuZGxlciByZWplY3RzIHNvIHRoZSBxdWV1ZSBjYW4gcmV0cnkuIEFmdGVyXG4gKiBgUkVQTEFZX1RJTUVPVVRfTUFYX1JFVFJJRVNgIGV4aGF1c3RlZCBhdHRlbXB0cyB0aGUgcnVuIGlzIGZhaWxlZCB3aXRoXG4gKiBgUlVOX0VSUk9SX0NPREVTLlJFUExBWV9USU1FT1VUYC5cbiAqXG4gKiBOb3RlIHRoYXQgb24gVmVyY2VsIEhvYmJ5IChzdGFuZGFyZCBmdW5jdGlvbnMpLCB0aGUgcGxhdGZvcm0gYG1heER1cmF0aW9uYFxuICogaXMgNjBzIOKAlCB3ZWxsIGJlbG93IHRoaXMgYnVkZ2V0LCBzbyB0aGUgcGxhdGZvcm0gU0lHVEVSTSB3aWxsIGZpcmUgZmlyc3RcbiAqIGFuZCB0aGUgcXVldWUgd2lsbCByZS1kZWxpdmVyIHVudGlsIHRoZSB2aXNpYmlsaXR5IHdpbmRvdyBleHBpcmVzLiBXaXRoXG4gKiBGbHVpZCBDb21wdXRlIG9uIEhvYmJ5IHRoZSBwZXItZnVuY3Rpb24gY2VpbGluZyByaXNlcyB0byAzMDBzLCBzdGlsbFxuICogdW5kZXIgdGhlIGRlZmF1bHQgYnVkZ2V0LlxuICpcbiAqIE92ZXJyaWRlIHZpYSB0aGUgYFdPUktGTE9XX1JFUExBWV9USU1FT1VUX01TYCBlbnYgdmFyIChjbGFtcGVkIHRvXG4gKiBgTUlOX1JFUExBWV9USU1FT1VUX01TYC4uYE1BWF9SRVBMQVlfVElNRU9VVF9NU2ApLlxuICovXG5leHBvcnQgY29uc3QgUkVQTEFZX1RJTUVPVVRfTVMgPSAyNDBfMDAwO1xuXG4vKiogTG93ZXIgYm91bmQgZm9yIHRoZSByZXBsYXktdGltZW91dCBlbnYgdmFyIG92ZXJyaWRlLiAqL1xuZXhwb3J0IGNvbnN0IE1JTl9SRVBMQVlfVElNRU9VVF9NUyA9IDMwXzAwMDtcblxuLyoqXG4gKiBVcHBlciBib3VuZCBmb3IgdGhlIHJlcGxheS10aW1lb3V0IGVudiB2YXIgb3ZlcnJpZGUuIDc4MHMgbGVhdmVzIOKJpTIwcyBvZlxuICogaGVhZHJvb20gdW5kZXIgVmVyY2VsIFBybyBGbHVpZCdzIDgwMHMgZnVuY3Rpb24gY2VpbGluZyBzbyB0aGUgaGFuZGxlclxuICogY2FuIHdyaXRlIGBydW5fZmFpbGVkYCBiZWZvcmUgU0lHVEVSTS5cbiAqL1xuZXhwb3J0IGNvbnN0IE1BWF9SRVBMQVlfVElNRU9VVF9NUyA9IDc4MF8wMDA7XG5cbi8vIFRyYWNrIHdoaWNoIHJhdyBlbnYgdmFyIHZhbHVlcyB3ZSd2ZSBhbHJlYWR5IHdhcm5lZCBhYm91dCBzbyB0aGUgd2FybmluZ1xuLy8gbG9nIG9ubHkgZmlyZXMgb25jZSBwZXIgcHJvY2VzcyAodGhlIGZ1bmN0aW9uIG1heSBiZSBjYWxsZWQgbWFueSB0aW1lcykuXG5jb25zdCB3YXJuZWRSZXBsYXlUaW1lb3V0VmFsdWVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbmZ1bmN0aW9uIHdhcm5PbmNlKFxuICByYXc6IHN0cmluZyxcbiAgbWVzc2FnZTogc3RyaW5nLFxuICBkYXRhOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPlxuKTogdm9pZCB7XG4gIGlmICh3YXJuZWRSZXBsYXlUaW1lb3V0VmFsdWVzLmhhcyhyYXcpKSByZXR1cm47XG4gIHdhcm5lZFJlcGxheVRpbWVvdXRWYWx1ZXMuYWRkKHJhdyk7XG4gIHJ1bnRpbWVMb2dnZXIud2FybihtZXNzYWdlLCBkYXRhKTtcbn1cblxuLyoqXG4gKiBSZXNvbHZlIHRoZSBlZmZlY3RpdmUgcmVwbGF5LXRpbWVvdXQgYnVkZ2V0IGZvciB0aGUgY3VycmVudCBwcm9jZXNzLlxuICpcbiAqIFJlYWRzIGBwcm9jZXNzLmVudi5XT1JLRkxPV19SRVBMQVlfVElNRU9VVF9NU2AgbGF6aWx5IHNvIHRlc3RzIGFuZFxuICogZGVwbG95bWVudHMgY2FuIG92ZXJyaWRlIHBlciBpbnZvY2F0aW9uLiBJbnZhbGlkIC8gb3V0LW9mLXJhbmdlIHZhbHVlc1xuICogZmFsbCBiYWNrIHRvIGEgc2FmZSB2YWx1ZSAobm8gdGhyb3cg4oCUIHRoZSBlbnYgdmFyIGlzIGFuIGVzY2FwZSBoYXRjaCxcbiAqIG5vdCBhIGhhcmQgcmVxdWlyZW1lbnQpIGFuZCBlbWl0IGEgb25lLXRpbWUgd2FybmluZyBzbyBtaXNjb25maWd1cmF0aW9uXG4gKiBpcyBvYnNlcnZhYmxlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0UmVwbGF5VGltZW91dE1zKCk6IG51bWJlciB7XG4gIGNvbnN0IHJhdyA9IHByb2Nlc3MuZW52LldPUktGTE9XX1JFUExBWV9USU1FT1VUX01TO1xuICBpZiAoIXJhdykgcmV0dXJuIFJFUExBWV9USU1FT1VUX01TO1xuICBjb25zdCBwYXJzZWQgPSBOdW1iZXIocmF3KTtcbiAgaWYgKCFOdW1iZXIuaXNGaW5pdGUocGFyc2VkKSB8fCBwYXJzZWQgPD0gMCkge1xuICAgIHdhcm5PbmNlKFxuICAgICAgcmF3LFxuICAgICAgJ0lnbm9yaW5nIFdPUktGTE9XX1JFUExBWV9USU1FT1VUX01TOiBub3QgYSBwb3NpdGl2ZSBmaW5pdGUgbnVtYmVyOyB1c2luZyBkZWZhdWx0JyxcbiAgICAgIHsgcmF3LCBkZWZhdWx0TXM6IFJFUExBWV9USU1FT1VUX01TIH1cbiAgICApO1xuICAgIHJldHVybiBSRVBMQVlfVElNRU9VVF9NUztcbiAgfVxuICBpZiAocGFyc2VkIDwgTUlOX1JFUExBWV9USU1FT1VUX01TKSB7XG4gICAgd2Fybk9uY2UocmF3LCAnV09SS0ZMT1dfUkVQTEFZX1RJTUVPVVRfTVMgYmVsb3cgbWluaW11bTsgY2xhbXBlZCcsIHtcbiAgICAgIHJhdyxcbiAgICAgIGNsYW1wZWRNczogTUlOX1JFUExBWV9USU1FT1VUX01TLFxuICAgICAgbWluTXM6IE1JTl9SRVBMQVlfVElNRU9VVF9NUyxcbiAgICB9KTtcbiAgICByZXR1cm4gTUlOX1JFUExBWV9USU1FT1VUX01TO1xuICB9XG4gIGlmIChwYXJzZWQgPiBNQVhfUkVQTEFZX1RJTUVPVVRfTVMpIHtcbiAgICB3YXJuT25jZShyYXcsICdXT1JLRkxPV19SRVBMQVlfVElNRU9VVF9NUyBhYm92ZSBtYXhpbXVtOyBjbGFtcGVkJywge1xuICAgICAgcmF3LFxuICAgICAgY2xhbXBlZE1zOiBNQVhfUkVQTEFZX1RJTUVPVVRfTVMsXG4gICAgICBtYXhNczogTUFYX1JFUExBWV9USU1FT1VUX01TLFxuICAgIH0pO1xuICAgIHJldHVybiBNQVhfUkVQTEFZX1RJTUVPVVRfTVM7XG4gIH1cbiAgcmV0dXJuIHBhcnNlZDtcbn1cblxuLyoqXG4gKiBSZXNldCB0aGUgd2Fybi1vbmNlIGNhY2hlLiBUZXN0LW9ubHkg4oCUIGV4cG9ydGVkIHNvIHVuaXQgdGVzdHMgY2FuXG4gKiBleGVyY2lzZSB0aGUgd2FybiBwYXRoIHJlcGVhdGVkbHkgd2l0aG91dCBzaGFyaW5nIHN0YXRlLlxuICpcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gX3Jlc2V0UmVwbGF5VGltZW91dFdhcm5DYWNoZUZvclRlc3RzKCk6IHZvaWQge1xuICB3YXJuZWRSZXBsYXlUaW1lb3V0VmFsdWVzLmNsZWFyKCk7XG59XG5cbi8vIE51bWJlciBvZiBxdWV1ZSBkZWxpdmVyeSBhdHRlbXB0cyB0byBhbGxvdyBiZWZvcmUgcGVybWFuZW50bHkgZmFpbGluZyBhIHJ1blxuLy8gZHVlIHRvIGEgcmVwbGF5IHRpbWVvdXQuIE9uIGF0dGVtcHRzIDEgdGhyb3VnaCB0aGlzIHZhbHVlLCB0aGUgdGltZW91dFxuLy8gaGFuZGxlciByZWplY3RzIHdpdGhvdXQgd3JpdGluZyBydW5fZmFpbGVkIHNvIHRoZSBxdWV1ZSByZXRyaWVzIHRoZSBtZXNzYWdlLlxuLy8gT24gdGhlIG5leHQgYXR0ZW1wdCB0aGUgcnVuIGlzIG1hcmtlZCBhcyBmYWlsZWQuXG5leHBvcnQgY29uc3QgUkVQTEFZX1RJTUVPVVRfTUFYX1JFVFJJRVMgPSAzO1xuXG4vKipcbiAqIEVmZmVjdGl2ZSByZXBsYXktdGltZW91dCByZXRyeSBidWRnZXQuIE92ZXJyaWRlIHZpYVxuICogYFdPUktGTE9XX1JFUExBWV9USU1FT1VUX01BWF9SRVRSSUVTYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFJlcGxheVRpbWVvdXRNYXhSZXRyaWVzKCk6IG51bWJlciB7XG4gIHJldHVybiBlbnZOdW1iZXIoXG4gICAgJ1dPUktGTE9XX1JFUExBWV9USU1FT1VUX01BWF9SRVRSSUVTJyxcbiAgICBSRVBMQVlfVElNRU9VVF9NQVhfUkVUUklFUyxcbiAgICB7IGludGVnZXI6IHRydWUgfVxuICApO1xufVxuXG4vKipcbiAqIERlZmF1bHQgbWF4aW11bSBudW1iZXIgb2Ygc3RlcHMgdGhlIG93bmVkLWlubGluZSBwYXRoIHJ1bnMgaW5saW5lIChpblxuICogcGFyYWxsZWwpIHBlciBzdXNwZW5zaW9uLiBUaGUgcmVzdCBhcmUgcXVldWVkIHRvIGJhY2tncm91bmQgaGFuZGxlcnMuIEVhY2hcbiAqIGlubGluZSBzdGVwIGlzIGNyZWF0ZWQgbGF6aWx5IOKAlCBpdHMgYHN0ZXBfY3JlYXRlZGAgaXMgZm9sZGVkIGludG8gdGhlXG4gKiBgc3RlcF9zdGFydGVkYCB0aGF0IGBleGVjdXRlU3RlcGAgc2VuZHMg4oCUIHNvIGlubGluaW5nIE4gc3RlcHMgc2F2ZXMgTiBxdWV1ZVxuICogcm91bmQtdHJpcHMgZm9yIGEgYFByb21pc2UuYWxsYC1zdHlsZSBmYW4tb3V0LiBgMWAgcmVwcm9kdWNlcyB0aGVcbiAqIHNpbmdsZS1pbmxpbmUtc3RlcCBiZWhhdmlvciBleGFjdGx5ICh1c2VmdWwga2lsbC1zd2l0Y2gpLlxuICpcbiAqIE92ZXJyaWRlIHZpYSBgV09SS0ZMT1dfTUFYX0lOTElORV9TVEVQU2AgKGNsYW1wZWQgdG9cbiAqIGBNSU5fTUFYX0lOTElORV9TVEVQU2AuLmBNQVhfTUFYX0lOTElORV9TVEVQU2ApLlxuICovXG5leHBvcnQgY29uc3QgTUFYX0lOTElORV9TVEVQUyA9IDM7XG5cbi8qKiBMb3dlciBib3VuZCBmb3IgdGhlIGlubGluZS1zdGVwcyBlbnYgb3ZlcnJpZGUgKDEgPSBzaW5nbGUgaW5saW5lIHN0ZXApLiAqL1xuZXhwb3J0IGNvbnN0IE1JTl9NQVhfSU5MSU5FX1NURVBTID0gMTtcblxuLyoqXG4gKiBVcHBlciBib3VuZCBmb3IgdGhlIGlubGluZS1zdGVwcyBlbnYgb3ZlcnJpZGUuIElubGluZSBib2RpZXMgcnVuIGluIHBhcmFsbGVsXG4gKiB3aXRoaW4gb25lIGZ1bmN0aW9uIGludm9jYXRpb24sIHNvIHRoaXMgY2FwcyBtZW1vcnkvQ1BVIGZhbi1vdXQgcGVyIGhhbmRsZXIuXG4gKi9cbmV4cG9ydCBjb25zdCBNQVhfTUFYX0lOTElORV9TVEVQUyA9IDE2O1xuXG4vLyBXYXJuLW9uY2UgY2FjaGUgZm9yIFdPUktGTE9XX01BWF9JTkxJTkVfU1RFUFMsIGtleWVkIGJ5IHJhdyBlbnYgdmFsdWUuXG5jb25zdCB3YXJuZWRNYXhJbmxpbmVTdGVwc1ZhbHVlcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4vKipcbiAqIFJlc29sdmUgdGhlIGVmZmVjdGl2ZSBtYXggbnVtYmVyIG9mIGlubGluZSBzdGVwcyBmb3IgdGhlIGN1cnJlbnQgcHJvY2Vzcy5cbiAqXG4gKiBSZWFkcyBgcHJvY2Vzcy5lbnYuV09SS0ZMT1dfTUFYX0lOTElORV9TVEVQU2AgbGF6aWx5IHNvIHRlc3RzIGFuZFxuICogZGVwbG95bWVudHMgY2FuIG92ZXJyaWRlIHBlciBpbnZvY2F0aW9uLiBJbnZhbGlkIC8gb3V0LW9mLXJhbmdlIHZhbHVlcyBmYWxsXG4gKiBiYWNrIHRvIGEgc2FmZSB2YWx1ZSAobm8gdGhyb3cg4oCUIHRoZSBlbnYgdmFyIGlzIGFuIGVzY2FwZSBoYXRjaCkgYW5kIGVtaXQgYVxuICogb25lLXRpbWUgd2FybmluZyBzbyBtaXNjb25maWd1cmF0aW9uIGlzIG9ic2VydmFibGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRNYXhJbmxpbmVTdGVwcygpOiBudW1iZXIge1xuICBjb25zdCByYXcgPSBwcm9jZXNzLmVudi5XT1JLRkxPV19NQVhfSU5MSU5FX1NURVBTO1xuICBpZiAoIXJhdykgcmV0dXJuIE1BWF9JTkxJTkVfU1RFUFM7XG4gIGNvbnN0IHBhcnNlZCA9IE51bWJlcihyYXcpO1xuICBpZiAoIU51bWJlci5pc0ludGVnZXIocGFyc2VkKSB8fCBwYXJzZWQgPD0gMCkge1xuICAgIGlmICghd2FybmVkTWF4SW5saW5lU3RlcHNWYWx1ZXMuaGFzKHJhdykpIHtcbiAgICAgIHdhcm5lZE1heElubGluZVN0ZXBzVmFsdWVzLmFkZChyYXcpO1xuICAgICAgcnVudGltZUxvZ2dlci53YXJuKFxuICAgICAgICAnSWdub3JpbmcgV09SS0ZMT1dfTUFYX0lOTElORV9TVEVQUzogbm90IGEgcG9zaXRpdmUgaW50ZWdlcjsgdXNpbmcgZGVmYXVsdCcsXG4gICAgICAgIHsgcmF3LCBkZWZhdWx0VmFsdWU6IE1BWF9JTkxJTkVfU1RFUFMgfVxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIE1BWF9JTkxJTkVfU1RFUFM7XG4gIH1cbiAgaWYgKHBhcnNlZCA8IE1JTl9NQVhfSU5MSU5FX1NURVBTKSByZXR1cm4gTUlOX01BWF9JTkxJTkVfU1RFUFM7XG4gIGlmIChwYXJzZWQgPiBNQVhfTUFYX0lOTElORV9TVEVQUykge1xuICAgIGlmICghd2FybmVkTWF4SW5saW5lU3RlcHNWYWx1ZXMuaGFzKHJhdykpIHtcbiAgICAgIHdhcm5lZE1heElubGluZVN0ZXBzVmFsdWVzLmFkZChyYXcpO1xuICAgICAgcnVudGltZUxvZ2dlci53YXJuKCdXT1JLRkxPV19NQVhfSU5MSU5FX1NURVBTIGFib3ZlIG1heGltdW07IGNsYW1wZWQnLCB7XG4gICAgICAgIHJhdyxcbiAgICAgICAgY2xhbXBlZFZhbHVlOiBNQVhfTUFYX0lOTElORV9TVEVQUyxcbiAgICAgICAgbWF4VmFsdWU6IE1BWF9NQVhfSU5MSU5FX1NURVBTLFxuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBNQVhfTUFYX0lOTElORV9TVEVQUztcbiAgfVxuICByZXR1cm4gcGFyc2VkO1xufVxuXG4vKipcbiAqIFVwcGVyIGJvdW5kIG9uIHRoZSBzZXJpYWxpemVkIHN0ZXAgaW5wdXQgdGhhdCByZXNpbGllbnQgc3RlcCBkaXNwYXRjaCB3aWxsXG4gKiBpbmxpbmUgaW50byB0aGUgcXVldWUgbWVzc2FnZSdzIGBzdGVwSW5wdXRgLlxuICpcbiAqIFZlcmNlbCBRdWV1ZXMgaGFzIG5vIGhhcmQgbWVzc2FnZS1zaXplIGNhcCAoYm9kaWVzIGFib3ZlIGl0cyB+MjU2IEtCXG4gKiBpbmxpbmUgdGhyZXNob2xkIHRyYW5zcGFyZW50bHkgc3BpbGwgdG8gUzMtYmFja2VkIHN0b3JhZ2UpLCBzbyB0aGlzIGJvdW5kXG4gKiBpcyBhIGNvc3QvbGF0ZW5jeSBjaG9pY2UsIG5vdCBhIHJlamVjdGlvbiBndWFyZDogdGhlIG1lc3NhZ2UgYWxzbyBjYXJyaWVzXG4gKiB0aGUgcnVuSWQsIHN0ZXBJZCwgc3RlcE5hbWUsIGFuZCB0cmFjZSBjYXJyaWVyIGFsb25nc2lkZSBDQk9SIGZyYW1pbmdcbiAqIG92ZXJoZWFkLCBhbmQgc3RheWluZyB1bmRlciB0aGUgcXVldWUncyBpbmxpbmUgdGhyZXNob2xkIGtlZXBzIHN0ZXBcbiAqIG1lc3NhZ2VzIG9uIGl0cyBmYXN0IGlubGluZSBwYXRoIGluc3RlYWQgb2YgcGF5aW5nIGFuIFMzIHN0b3JlK2ZldGNoXG4gKiBkb3VibGUtaG9wIGZvciBieXRlcyB0aGF0IGFscmVhZHkgbGl2ZSBpbiB0aGUgZXZlbnQgbG9nLiBBYm92ZSB0aGlzIHNpemVcbiAqIHRoZSBkaXNwYXRjaCBmYWxscyBiYWNrIHRvIHRoZSBzZXF1ZW50aWFsIHBhdGggKGBzdGVwX2NyZWF0ZWRgIHdyaXRlLCB0aGVuXG4gKiBhIHBheWxvYWQtbGVzcyBxdWV1ZSBtZXNzYWdlKS4gTWF0Y2hlcyBgTUFYX0lOTElORV9SRVNVTUVfUEFZTE9BRF9CWVRFU2BcbiAqIG9uIHRoZSByZXNpbGllbnQgaG9vayByZXN1bWUgcGF0aC5cbiAqL1xuZXhwb3J0IGNvbnN0IE1BWF9SRVNJTElFTlRfU1RFUF9JTlBVVF9CWVRFUyA9IDEyOCAqIDEwMjQ7XG5cbi8qKlxuICogV2hldGhlciByZXNpbGllbnQgc3RlcCBkaXNwYXRjaCBpcyBlbmFibGVkOiB0aGUgc3VzcGVuc2lvbiBoYW5kbGVyXG4gKiBwYXJhbGxlbGl6ZXMgZWFjaCBuZXdseSBjcmVhdGVkIHN0ZXAncyBgc3RlcF9jcmVhdGVkYCBldmVudCB3cml0ZSB3aXRoIGl0c1xuICogc3RlcC1leGVjdXRpb24gcXVldWUgcHVibGlzaCwgY2FycnlpbmcgdGhlIHNlcmlhbGl6ZWQgc3RlcCBpbnB1dCBpbiB0aGVcbiAqIHF1ZXVlIG1lc3NhZ2UgKGBzdGVwSW5wdXRgKSBzbyB0aGUgY29uc3VtZXIgY2FuIGlkZW1wb3RlbnRseSByZS1lbnN1cmUgdGhlXG4gKiBldmVudCBpZiB0aGUgZGlyZWN0IHdyaXRlIGZhaWxlZCB0cmFuc2llbnRseS4gTWlycm9ycyB0aGUgcmVzaWxpZW50IHN0YXJ0XG4gKiAoYHJ1bklucHV0YCkgYW5kIHJlc2lsaWVudCBob29rIHJlc3VtZSAoYGhvb2tJbnB1dGApIHBhdHRlcm5zLlxuICpcbiAqICoqT2ZmIGJ5IGRlZmF1bHQuKiogRW5hYmxlIHZpYSBgV09SS0ZMT1dfUkVTSUxJRU5UX1NURVBfRElTUEFUQ0g9MWAuXG4gKlxuICogVGhlIHF1ZXVlIHB1Ymxpc2ggcmFjZXMgdGhlIGNyZWF0ZSdzIHZlcmRpY3QsIGFuZCBhIGNyZWF0ZSBjYW4gY29tZSBiYWNrXG4gKiByZWZ1c2VkIOKAlCBhcyBhIGR1cGxpY2F0ZSB0aGlzIHJlcGxheSBzaG91bGQgc3RvcCBwdXJzdWluZywgb3IgYXMgYSBzdGFsZVxuICogd3JpdGUgb24gYSBXb3JsZCB0aGF0IHJlZnVzZXMgcmF0aGVyIHRoYW4gcmVwb3J0cy4gRWl0aGVyIHdheSB0aGUgbWVzc2FnZVxuICogY2FycnlpbmcgdGhlIHBheWxvYWQgaXMgYWxyZWFkeSBvdXQsIHNvIHRoZSBjb25zdW1lciBjYW4gbWF0ZXJpYWxpemUgYSBzdGVwXG4gKiB3aG9zZSBjcmVhdGUgd2FzIHJlZnVzZWQsIGFuZCBub3RoaW5nIG9yZGVycyB0aGUgdmVyZGljdCBiZWZvcmUgdGhlXG4gKiBjb25zdW1lcidzIHJlZGVsaXZlcnkgcmUtZW5zdXJlLiBFbmFibGluZyB0aGlzIHRyYWRlcyB0aGF0IHdpbmRvdyBmb3IgdGhlXG4gKiBsYXRlbmN5IHRoZSBwYXJhbGxlbCBwdWJsaXNoIHNhdmVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNSZXNpbGllbnRTdGVwRGlzcGF0Y2hFbmFibGVkKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gcHJvY2Vzcy5lbnYuV09SS0ZMT1dfUkVTSUxJRU5UX1NURVBfRElTUEFUQ0ggPT09ICcxJztcbn1cblxuY29uc3Qgd2FybmVkTWF4RXZlbnRzVmFsdWVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbi8qKlxuICogT3B0aW9uYWwgY2xpZW50LXNpZGUgb3ZlcnJpZGUgZm9yIHRoZSBzZXJ2ZXItc3VwcGxpZWQgcGVyLXJ1biBldmVudCBjZWlsaW5nLlxuICogV2hlbiBzZXQgdG8gYSBwb3NpdGl2ZSBpbnRlZ2VyLCB0aGUgcnVudGltZSBjbGFtcHMgdGhlIHNlcnZlcidzIGxpbWl0ICpkb3duKlxuICogdG8gdGhpcyB2YWx1ZSAobmV2ZXIgcmFpc2VzIGl0KSBzbyBlbmZvcmNlbWVudCBjYW4gYmUgZXhlcmNpc2VkIHdpdGhvdXQgYVxuICogc2VydmVyLXNpZGUgY2hhbmdlLiBgdW5kZWZpbmVkYCAodW5zZXQpIOKHkiB1c2UgdGhlIHNlcnZlciB2YWx1ZSBhcy1pcy5cbiAqXG4gKiBSZWFkcyBgcHJvY2Vzcy5lbnYuV09SS0ZMT1dfTUFYX0VWRU5UU19PVkVSUklERWAgbGF6aWx5IHNvIHRlc3RzIGFuZFxuICogZGVwbG95bWVudHMgY2FuIG92ZXJyaWRlIHBlciBpbnZvY2F0aW9uLiBJbnZhbGlkIHZhbHVlcyBmYWxsIGJhY2sgdG8gdW5zZXRcbiAqIChubyB0aHJvdyDigJQgdGhlIGVudiB2YXIgaXMgYW4gZXNjYXBlIGhhdGNoKSBhbmQgZW1pdCBhIG9uZS10aW1lIHdhcm5pbmcuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRNYXhFdmVudHNPdmVycmlkZSgpOiBudW1iZXIgfCB1bmRlZmluZWQge1xuICBjb25zdCByYXcgPSBwcm9jZXNzLmVudi5XT1JLRkxPV19NQVhfRVZFTlRTX09WRVJSSURFO1xuICBpZiAoIXJhdykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgY29uc3QgcGFyc2VkID0gTnVtYmVyKHJhdyk7XG4gIGlmICghTnVtYmVyLmlzSW50ZWdlcihwYXJzZWQpIHx8IHBhcnNlZCA8PSAwKSB7XG4gICAgaWYgKCF3YXJuZWRNYXhFdmVudHNWYWx1ZXMuaGFzKHJhdykpIHtcbiAgICAgIHdhcm5lZE1heEV2ZW50c1ZhbHVlcy5hZGQocmF3KTtcbiAgICAgIHJ1bnRpbWVMb2dnZXIud2FybihcbiAgICAgICAgJ0lnbm9yaW5nIFdPUktGTE9XX01BWF9FVkVOVFNfT1ZFUlJJREU6IG5vdCBhIHBvc2l0aXZlIGludGVnZXI7IHVzaW5nIHNlcnZlciBsaW1pdCcsXG4gICAgICAgIHsgcmF3IH1cbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbiAgcmV0dXJuIHBhcnNlZDtcbn1cblxuLyoqXG4gKiBXaGV0aGVyIG9wdGltaXN0aWMgaW5saW5lIHN0ZXAgc3RhcnQgaXMgZW5hYmxlZC4gV2hlbiBvbiwgdGhlIG93bmVkLWlubGluZVxuICogcGF0aCBiZWdpbnMgcnVubmluZyBhIGJyYW5kLW5ldyBzdGVwJ3MgYm9keSAqYmVmb3JlKiBpdHMgbGF6eSBgc3RlcF9zdGFydGVkYFxuICogbmV0d29yayBjYWxsIHJlc29sdmVzICh0aGUgaW5wdXQgaXMgYWxyZWFkeSBrbm93biBsb2NhbGx5KSwgYXdhaXRpbmcgdGhlXG4gKiBgc3RlcF9zdGFydGVkYCBvbmx5IGJlZm9yZSB0aGUgdGVybWluYWwgd3JpdGUuXG4gKlxuICogVGhpcyBjYW4gcnVuIGEgc3RlcCBib2R5IG1vcmUgdGhhbiBvbmNlIHdoZW4gaGFuZGxlcnMgcmFjZSBmb3IgdGhlIHNhbWVcbiAqIHN0ZXAncyBjcmVhdGUtY2xhaW0g4oCUIGJvdGggcnVuIHRoZSBib2R5IGJlZm9yZSBvbmUgd2lucy4gVGhhdCBpcyB1bnNhZmUgZm9yXG4gKiBzdGVwcyB3aXRoIG5vbi1pZGVtcG90ZW50IHNpZGUgZWZmZWN0czsgaW4gcGFydGljdWxhciwgdHdvIGNvbmN1cnJlbnQgcnVuc1xuICogb2YgYSBzdGVwIHRoYXQgd3JpdGVzIHRvIHRoZSB3b3JrZmxvdyBzdHJlYW0gKGUuZy4gYW4gQUkgYWdlbnQgc3RyZWFtaW5nXG4gKiB0b2tlbnMpIGNhbiBpbnRlcmxlYXZlIGFuZCBjb3JydXB0IHRoZSBzdHJlYW0gZGF0YS4gU28gdGhlIG9wdGltaXphdGlvbiBpc1xuICogKipvZmYgYnkgZGVmYXVsdCoqIGFuZCBtdXN0IGJlIGV4cGxpY2l0bHkgb3B0ZWQgaW50byBwZXIgZGVwbG95bWVudC5cbiAqXG4gKiBSZWFkcyBgcHJvY2Vzcy5lbnYuV09SS0ZMT1dfT1BUSU1JU1RJQ19JTkxJTkVfU1RBUlRgIGxhemlseS4gRGVmYXVsdCBPRkY7XG4gKiBlbmFibGVkIG9ubHkgYnkgYW4gZXhwbGljaXQgYCcxJ2AgLyBgJ3RydWUnYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzT3B0aW1pc3RpY0lubGluZVN0YXJ0RW5hYmxlZCgpOiBib29sZWFuIHtcbiAgY29uc3QgcmF3ID0gcHJvY2Vzcy5lbnYuV09SS0ZMT1dfT1BUSU1JU1RJQ19JTkxJTkVfU1RBUlQ7XG4gIGlmIChyYXcgPT09IHVuZGVmaW5lZCB8fCByYXcgPT09ICcnKSByZXR1cm4gZmFsc2U7XG4gIHJldHVybiByYXcgPT09ICcxJyB8fCByYXcudG9Mb3dlckNhc2UoKSA9PT0gJ3RydWUnO1xufVxuXG4vKipcbiAqIFdoZXRoZXIgYW4gb3BlcmF0b3IgaGFzICoqZXhwbGljaXRseSBkaXNhYmxlZCoqIG9wdGltaXN0aWMgaW5saW5lIHN0YXJ0IHZpYVxuICogYFdPUktGTE9XX09QVElNSVNUSUNfSU5MSU5FX1NUQVJUPTBgIC8gYD1mYWxzZWAuIERpc3RpbmN0IGZyb20gXCJ1bnNldFwiOiB1bnNldFxuICogbGVhdmVzIHRoZSBvcHRpbWl6YXRpb24gb2ZmIGJ5IGRlZmF1bHQgYnV0IGxldHMgdHVyYm8gZm9yY2UgaXQgb247IGFuIGV4cGxpY2l0XG4gKiBgMGAvYGZhbHNlYCBpcyBhbiBvcGVyYXRvciBvcHQtb3V0IHRoYXQgdHVyYm8gbXVzdCBob25vciAodHVyYm8ncyBmb3JjZWRcbiAqIG9wdGltaXN0aWMgc3RhcnQgc3RpbGwgcnVucyBhIHN0ZXAgYm9keSBiZWZvcmUgYHN0ZXBfc3RhcnRlZGAvYHJ1bl9zdGFydGVkYCBpc1xuICogY29uZmlybWVkLCB0aGUgcHJvcGVydHkgc3VjaCBhbiBvcGVyYXRvciBpcyBvcHRpbmcgb3V0IG9mKSwgc29cbiAqIGBmb3JjZU9wdGltaXN0aWNTdGFydGAgZGVmZXJzIHRvIHRoaXMuIFJlYWRzIHRoZSBlbnYgdmFyIGxhemlseS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzT3B0aW1pc3RpY0lubGluZVN0YXJ0RXhwbGljaXRseURpc2FibGVkKCk6IGJvb2xlYW4ge1xuICBjb25zdCByYXcgPSBwcm9jZXNzLmVudi5XT1JLRkxPV19PUFRJTUlTVElDX0lOTElORV9TVEFSVDtcbiAgaWYgKHJhdyA9PT0gdW5kZWZpbmVkIHx8IHJhdyA9PT0gJycpIHJldHVybiBmYWxzZTtcbiAgcmV0dXJuIHJhdyA9PT0gJzAnIHx8IHJhdy50b0xvd2VyQ2FzZSgpID09PSAnZmFsc2UnO1xufVxuXG4vKipcbiAqIFdoZXRoZXIgXCJ0dXJibyBtb2RlXCIgaXMgZW5hYmxlZC4gVHVyYm8gbW9kZSBmYXN0LXBhdGhzIHRoZSAqZmlyc3QgZGVsaXZlcnkgb2ZcbiAqIHRoZSBmaXJzdCBpbnZvY2F0aW9uKiBvZiBhIHJ1biAoZGV0ZWN0ZWQgYnkgdGhlIGVudHJ5cG9pbnQgdmlhIGBydW5JbnB1dGBcbiAqIHByZXNlbmNlICsgYG1ldGFkYXRhLmF0dGVtcHQgPT09IDFgKTogaXQgYmFja2dyb3VuZHMgdGhlIGBydW5fc3RhcnRlZGAgZXZlbnRcbiAqIGNyZWF0aW9uLCBza2lwcyB0aGUgaW5pdGlhbCBldmVudC1sb2cgbG9hZCAobm90aGluZyBoYXMgYmVlbiB3cml0dGVuIHlldCksXG4gKiBhbmQgZm9yY2VzIG9wdGltaXN0aWMgaW5saW5lIHN0ZXAgc3RhcnQgZm9yIHRoYXQgaW52b2NhdGlvbiDigJQgaW5kZXBlbmRlbnQgb2ZcbiAqIGBXT1JLRkxPV19PUFRJTUlTVElDX0lOTElORV9TVEFSVGAuXG4gKlxuICogRm9yY2luZyBvcHRpbWlzdGljIHN0YXJ0IGlzIHNhZmUgaGVyZSBiZWNhdXNlIHRoZSBmaXJzdCBkZWxpdmVyeSBoYXMgbm9cbiAqIGNvbmN1cnJlbnQgcGVlciBoYW5kbGVyIHRvIHJhY2UgdGhlIHN0ZXAgY3JlYXRlLWNsYWltLCBzbyBhIHN0ZXAgYm9keSBydW5zXG4gKiBleGFjdGx5IG9uY2UuIFRoYXQgc2luZ2xlLWhhbmRsZXIgZ3VhcmFudGVlIGVuZHMgYXMgc29vbiBhcyB0aGUgcnVuIGNyZWF0ZXMgYVxuICogaG9vayBvciB3YWl0ICh3aGljaCBpbnRyb2R1Y2UgcmVzdW1lL3BhcmFsbGVsIGludm9jYXRpb25zKSwgc28gdGhlIHJ1bnRpbWVcbiAqIGV4aXRzIHR1cmJvIGF0IHRoYXQgcG9pbnQuXG4gKlxuICogUmVhZHMgYHByb2Nlc3MuZW52LldPUktGTE9XX1RVUkJPYCBsYXppbHkuIERlZmF1bHQgKipPTioqOyBkaXNhYmxlZCBvbmx5IGJ5IGFuXG4gKiBleHBsaWNpdCBgJzAnYCAvIGAnZmFsc2UnYCAoY2FzZS1pbnNlbnNpdGl2ZSkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1R1cmJvRW5hYmxlZCgpOiBib29sZWFuIHtcbiAgY29uc3QgcmF3ID0gcHJvY2Vzcy5lbnYuV09SS0ZMT1dfVFVSQk87XG4gIGlmIChyYXcgPT09IHVuZGVmaW5lZCB8fCByYXcgPT09ICcnKSByZXR1cm4gdHJ1ZTtcbiAgcmV0dXJuICEocmF3ID09PSAnMCcgfHwgcmF3LnRvTG93ZXJDYXNlKCkgPT09ICdmYWxzZScpO1xufVxuXG4vKipcbiAqIFdoZXRoZXIgdGhlIFF1aWNrSlMgZW5naW5lJ3MgYmFzZWxpbmUtc25hcHNob3Qgc3RhcnR1cCBvcHRpbWl6YXRpb24gaXNcbiAqIGVuYWJsZWQgKGRlZmF1bHQgT04pLiBXaGVuIG9uLCB0aGUgZW5naW5lIGh5ZHJhdGVzIGEgVk0gd2l0aCB0aGVcbiAqIHdvcmtmbG93IGJ1bmRsZSBvbmNlIHBlciBmdW5jdGlvbiBpbnN0YW5jZSwgc25hcHNob3RzIGl0LCBhbmQgc3RhcnRzXG4gKiBldmVyeSBpbnZvY2F0aW9uIGJ5IHJlc3RvcmluZyB0aGUgc25hcHNob3QgaW5zdGVhZCBvZiByZS1ldmFsdWF0aW5nXG4gKiB0aGUgYnVuZGxlIOKAlCBza2lwcGluZyB0aGUgZG9taW5hbnQgc2hhcmUgb2YgVk0gc3RhcnR1cCAobWVhc3VyZWRcbiAqIH43N21zIOKGkiB+M21zIHRvIGZpcnN0IHN1c3BlbnNpb24gZm9yIGEgMS4zTUIgYnVuZGxlKS4gQnVuZGxlcyB3aG9zZVxuICogbW9kdWxlIHNjb3BlIGNvbnN1bWVzIHJhbmRvbW5lc3MsIHJlYWRzIHRoZSBjbG9jaywgb3IgcmVwbGFjZXMgYVxuICogc2VyaWFsaXphdGlvbiBpbnRyaW5zaWMgYXJlIGRldGVjdGVkIGF0IGh5ZHJhdGUgdGltZSBhbmRcbiAqIGF1dG9tYXRpY2FsbHkgZmFsbCBiYWNrIHRvIHBlci1pbnZvY2F0aW9uIGZyZXNoIGV2YWx1YXRpb24gKHNlZVxuICogcHJlcGFyZUJhc2VsaW5lU25hcHNob3QpLiBTZXQgV09SS0ZMT1dfUVVJQ0tKU19CQVNFTElORV9TTkFQU0hPVD0wIHRvXG4gKiBkaXNhYmxlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNRdWlja0pTQmFzZWxpbmVTbmFwc2hvdEVuYWJsZWQoKTogYm9vbGVhbiB7XG4gIGNvbnN0IHJhdyA9IHByb2Nlc3MuZW52LldPUktGTE9XX1FVSUNLSlNfQkFTRUxJTkVfU05BUFNIT1Q7XG4gIGlmIChyYXcgPT09IHVuZGVmaW5lZCB8fCByYXcgPT09ICcnKSByZXR1cm4gdHJ1ZTtcbiAgcmV0dXJuICEocmF3ID09PSAnMCcgfHwgcmF3LnRvTG93ZXJDYXNlKCkgPT09ICdmYWxzZScpO1xufVxuXG4vKipcbiAqIFdoZXRoZXIgdGhlIGlubGluZSBsb29wIHJldGFpbnMgYSBzdXNwZW5kZWQgd29ya2Zsb3cgVk0gYWNyb3NzIGlubGluZSBzdGVwc1xuICogd2l0aGluIG9uZSBpbnZvY2F0aW9uIChkZWZhdWx0IE9OKS4gV2hlbiBvbiwgYSBzdGVwLW9ubHkgc3VzcGVuc2lvbiBrZWVwc1xuICogdGhlIGxpdmUgVk0sIGV2ZW50IGNvbnN1bWVyLCBhbmQgaHlkcmF0ZWQgc3RhdGUgYWxpdmUsIGFuZCB0aGUgbmV4dCBsb29wXG4gKiBpdGVyYXRpb24gYXBwZW5kcyBvbmx5IHRoZSBuZXdseSBkdXJhYmxlIGV2ZW50cyBpbnN0ZWFkIG9mIHJlYnVpbGRpbmcgdGhlXG4gKiBgdm0uQ29udGV4dGAgYW5kIHJlcGxheWluZyB0aGUgd2hvbGUgZXZlbnQgbG9nLiBOb24tc3RlcCBzdXNwZW5zaW9ucyBhbmRcbiAqIHJlcGxheSBkaXZlcmdlbmNlIGFsd2F5cyBmYWxsIGJhY2sgdG8gdGhlIG9yZGluYXJ5IGR1cmFibGUgcmVwbGF5IHBhdGguXG4gKlxuICogYFdPUktGTE9XX1JFVEFJTkVEX1ZNPTBgIChvciBgZmFsc2VgKSBpcyB0aGUga2lsbCBzd2l0Y2g6IGV2ZXJ5IGl0ZXJhdGlvblxuICogcmVwbGF5cyBmcm9tIHNjcmF0Y2ggaW4gYSBmcmVzaCBWTSwgbWF0Y2hpbmcgdGhlIHByZS1yZXRlbnRpb24gYmVoYXZpb3IuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1ZtUmV0ZW50aW9uRW5hYmxlZCgpOiBib29sZWFuIHtcbiAgY29uc3QgcmF3ID0gcHJvY2Vzcy5lbnYuV09SS0ZMT1dfUkVUQUlORURfVk07XG4gIGlmIChyYXcgPT09IHVuZGVmaW5lZCB8fCByYXcgPT09ICcnKSByZXR1cm4gdHJ1ZTtcbiAgcmV0dXJuICEocmF3ID09PSAnMCcgfHwgcmF3LnRvTG93ZXJDYXNlKCkgPT09ICdmYWxzZScpO1xufVxuXG4vKipcbiAqIFdoZXRoZXIgaW5saW5lIHN0ZXAgb3duZXJzaGlwIGlzIGVuYWJsZWQgKGRlZmF1bHQgT04pLiBXaGVuIG9uLCB0aGUgbGF6eVxuICogYHN0ZXBfc3RhcnRlZGAgdGhhdCBjcmVhdGVzIGFuIGlubGluZSBzdGVwIHJlY29yZHMgdGhlIG93bmluZyBxdWV1ZVxuICogbWVzc2FnZSBJRCwgYW5kIHdha2UgcmVwbGF5cyB0aGF0IG9ic2VydmUgYW4gYWN0aXZlbHktb3duZWQgc3RlcCBlbnF1ZXVlIGFcbiAqICpkZWxheWVkIGJhY2tzdG9wKiBtZXNzYWdlIGluc3RlYWQgb2YgaW1tZWRpYXRlbHkgcmVxdWV1ZWluZyBpdCDigJQgZml4aW5nXG4gKiBkdXBsaWNhdGUgaW5saW5lIHN0ZXAgZXhlY3V0aW9uIHdoZW4gYSBob29rL3dhaXQgd2FrZXMgYSBydW4gbWlkLXN0ZXBcbiAqICh2ZXJjZWwvd29ya2Zsb3cjMjc4MCkuXG4gKlxuICogYFdPUktGTE9XX0lOTElORV9PV05FUlNISVA9MGAgKG9yIGBmYWxzZWApIGlzIHRoZSBraWxsIHN3aXRjaDogZGlzcGF0Y2hcbiAqIHJldmVydHMgdG8gdGhlIHVuY29uZGl0aW9uYWwgaW1tZWRpYXRlIHJlcXVldWUuIFN0YW1waW5nIGlzIHVuYWZmZWN0ZWQg4oCUXG4gKiB0aGUgcmVjb3JkZWQgb3duZXJNZXNzYWdlSWQgaXMgaW5lcnQgZGF0YSB3aGVuIHRoZSBzd2l0Y2ggaXMgb2ZmLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNJbmxpbmVPd25lcnNoaXBFbmFibGVkKCk6IGJvb2xlYW4ge1xuICBjb25zdCByYXcgPSBwcm9jZXNzLmVudi5XT1JLRkxPV19JTkxJTkVfT1dORVJTSElQO1xuICBpZiAocmF3ID09PSB1bmRlZmluZWQgfHwgcmF3ID09PSAnJykgcmV0dXJuIHRydWU7XG4gIHJldHVybiAhKHJhdyA9PT0gJzAnIHx8IHJhdy50b0xvd2VyQ2FzZSgpID09PSAnZmFsc2UnKTtcbn1cblxuLyoqXG4gKiBEZWZhdWx0IGlubGluZS1vd25lcnNoaXAgbGVhc2UsIGluIHNlY29uZHM6IGhvdyBsb25nIGFmdGVyIGEgc3RlcCdzIGxhdGVzdFxuICogKHN0YW1wZWQpIGBzdGVwX3N0YXJ0ZWRgIGEgbm9uLW93bmVyIGludm9jYXRpb24gYXNzdW1lcyB0aGUgb3duaW5nXG4gKiBpbnZvY2F0aW9uIG1heSBzdGlsbCBiZSBhbGl2ZS4gV2l0aGluIHRoZSBsZWFzZSwgd2FrZSByZXBsYXlzIGVucXVldWUgdGhlXG4gKiBzdGVwJ3MgYmFja3N0b3AgbWVzc2FnZSB3aXRoIGBkZWxheVNlY29uZHMgPSBsZWFzZSByZW1haW5pbmdgIGluc3RlYWQgb2ZcbiAqIGltbWVkaWF0ZWx5OyBwYXN0IGl0LCB0aGV5IGVucXVldWUgaW1tZWRpYXRlbHkgKHRvZGF5J3MgYmVoYXZpb3IpLlxuICpcbiAqIFdoeSBhIGZpeGVkIDg2MCBhbmQgbm90IGEgdmFsdWUgZGVyaXZlZCBmcm9tIHRoZSBmdW5jdGlvbidzIGBtYXhEdXJhdGlvbmA6XG4gKiBuZWl0aGVyIHJ1bnRpbWUgbm9yIGJ1aWxkIHRpbWUgY2FuIHNlZSB0aGUgcmVzb2x2ZWQgdmFsdWUg4oCUIGJ1aWxkZXJzIGVtaXRcbiAqIGBtYXhEdXJhdGlvbjogJ21heCdgLCB3aGljaCB0aGUgcGxhdGZvcm0gcmVzb2x2ZXMgcGVyLXBsYW4gYXQgZGVwbG95LCBhbmRcbiAqIG5vIGVudiB2YXIgb3IgcmVxdWVzdC1jb250ZXh0IGRlYWRsaW5lIEFQSSBleHBvc2VzIHRoZSByZXN1bHQuIFRoZSBib3VuZFxuICogY29tZXMgZnJvbSBhIHBsYXRmb3JtIHJ1bGUgaW5zdGVhZDogZHVyYXRpb25zIGFib3ZlIDgwMHMgcmVxdWlyZSBleHBsaWNpdFxuICogcGVyLWZ1bmN0aW9uIG51bWVyaWMgY29uZmlnLCBzbyBhIGJ1aWxkZXItZW1pdHRlZCBgJ21heCdgIHJlc29sdmVzIHRvIGF0XG4gKiBtb3N0IDgwMHMg4oCUIDg2MHMgdGhlcmVmb3JlIGRvbWluYXRlcyBhbnkgd29ya2Zsb3cgcm91dGUncyBpbnZvY2F0aW9uXG4gKiBsaWZldGltZSBwbHVzIHNjaGVkdWxpbmcgc2xhY2suIFJldmlzaXQgd2hlbiB0aGF0IGNlaWxpbmcgbW92ZXMgKHRoZVxuICogMzAtbWludXRlIGR1cmF0aW9uIGJldGEgYmVjb21pbmcgcmVhY2hhYmxlIHZpYSBgJ21heCdgIHdvdWxkIGludmFsaWRhdGVcbiAqIHRoZSBib3VuZCkuIFdvcmxkcyB3aXRob3V0IGFuIGludm9jYXRpb24ga2lsbCBib3VuZCAod29ybGQtbG9jYWwsXG4gKiBzZWxmLWhvc3RlZCkgZ2V0IG5vIGRlYXRoIHByb29mIGZyb20gYW55IGNvbnN0YW50IOKAlCB0aGVyZSB0aGUgaW4tcHJvY2Vzc1xuICogc2luZ2xlLWZsaWdodCBsYXllciAoc3RlcC1zaW5nbGUtZmxpZ2h0LnRzKSBpcyB3aGF0IG1ha2VzIGEgYmFja3N0b3BcbiAqIGZpcmluZyBtaWQtc3RlcCBoYXJtbGVzcy5cbiAqXG4gKiA4NjAgYWxzbyBzdGF5cyB1bmRlciB0aGUgcXVldWUncyA5MDBzIG1heGltdW0gZGVsYXkgKFNRUyBjYXApLCBzbyBhXG4gKiBiYWNrc3RvcCdzIGZ1bGwgbGVhc2UgcmVtYWluZGVyIGFsd2F5cyBmaXRzIGluIGEgc2luZ2xlIGRlbGF5ZWQgbWVzc2FnZS5cbiAqXG4gKiBPdmVycmlkZSB2aWEgYFdPUktGTE9XX0lOTElORV9PV05FUlNISVBfTEVBU0VfU0VDT05EU2AgKGNsYW1wZWQgdG9cbiAqIDEuLmBNQVhfSU5MSU5FX09XTkVSU0hJUF9MRUFTRV9TRUNPTkRTYCkuXG4gKi9cbmV4cG9ydCBjb25zdCBJTkxJTkVfT1dORVJTSElQX0xFQVNFX1NFQ09ORFMgPSA4NjA7XG5cbi8qKlxuICogVXBwZXIgYm91bmQgZm9yIHRoZSBsZWFzZSBlbnYgb3ZlcnJpZGUuIDkwMHMgaXMgdGhlIHF1ZXVlJ3MgbWF4aW11bVxuICogcGVyLW1lc3NhZ2UgZGVsYXkgKFNRUyBjYXApIOKAlCBhIGxvbmdlciBsZWFzZSB3b3VsZCBuZWVkIGRlbGF5IGNoYWluaW5nXG4gKiBsaWtlIGxvbmcgd2FpdHMgdXNlOyBjbGFtcCBpbnN0ZWFkIHNvIG9uZSBkZWxheWVkIG1lc3NhZ2UgYWx3YXlzIHN1ZmZpY2VzLlxuICovXG5leHBvcnQgY29uc3QgTUFYX0lOTElORV9PV05FUlNISVBfTEVBU0VfU0VDT05EUyA9IDkwMDtcblxuLyoqXG4gKiBFZmZlY3RpdmUgaW5saW5lLW93bmVyc2hpcCBsZWFzZS4gT3ZlcnJpZGUgdmlhXG4gKiBgV09SS0ZMT1dfSU5MSU5FX09XTkVSU0hJUF9MRUFTRV9TRUNPTkRTYCDigJQgZS5nLiByYWlzZSBpdCBvbiBzZWxmLWhvc3RlZFxuICogbXVsdGktaW5zdGFuY2Ugd29ybGRzIHdpdGggbG9uZy1ydW5uaW5nIHN0ZXBzIHRvIHdpZGVuIHRoZSB3aW5kb3cgaW4gd2hpY2hcbiAqIGEgbGl2ZSBvd25lciBpcyBwcm90ZWN0ZWQgZnJvbSBhIGNvbmN1cnJlbnQgYmFja3N0b3AgZXhlY3V0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0SW5saW5lT3duZXJzaGlwTGVhc2VTZWNvbmRzKCk6IG51bWJlciB7XG4gIHJldHVybiBlbnZOdW1iZXIoXG4gICAgJ1dPUktGTE9XX0lOTElORV9PV05FUlNISVBfTEVBU0VfU0VDT05EUycsXG4gICAgSU5MSU5FX09XTkVSU0hJUF9MRUFTRV9TRUNPTkRTLFxuICAgIHsgaW50ZWdlcjogdHJ1ZSwgbWluOiAxLCBtYXg6IE1BWF9JTkxJTkVfT1dORVJTSElQX0xFQVNFX1NFQ09ORFMgfVxuICApO1xufVxuXG4vLyBBIHJlcGxheS1jb25zdW1lciBtaXNtYXRjaCBjYW4gYmUgY2F1c2VkIGJ5IGEgdHJhbnNpZW50IGRpdmVyZ2VudCByZXBsYXlcbi8vIHJhdGhlciB0aGFuIGFuIGludmFsaWQgcGVyc2lzdGVkIGhpc3RvcnkuIFF1ZXVlIGJvdW5kZWQgcmVjb3ZlcnkgcmVwbGF5c1xuLy8gYmVmb3JlIHJlY29yZGluZyB0ZXJtaW5hbCBjb3JydXB0aW9uIGZvciBhIHJ1biB0aGF0IGNhbm5vdCByZXBsYXkuXG5leHBvcnQgY29uc3QgUkVQTEFZX0RJVkVSR0VOQ0VfTUFYX1JFVFJJRVMgPSAzO1xuXG4vKipcbiAqIEVmZmVjdGl2ZSByZXBsYXktZGl2ZXJnZW5jZSByZWNvdmVyeSBidWRnZXQuIE92ZXJyaWRlIHZpYVxuICogYFdPUktGTE9XX1JFUExBWV9ESVZFUkdFTkNFX01BWF9SRVRSSUVTYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFJlcGxheURpdmVyZ2VuY2VNYXhSZXRyaWVzKCk6IG51bWJlciB7XG4gIHJldHVybiBlbnZOdW1iZXIoXG4gICAgJ1dPUktGTE9XX1JFUExBWV9ESVZFUkdFTkNFX01BWF9SRVRSSUVTJyxcbiAgICBSRVBMQVlfRElWRVJHRU5DRV9NQVhfUkVUUklFUyxcbiAgICB7IGludGVnZXI6IHRydWUgfVxuICApO1xufVxuXG4vLyBBIHN0YWxlLXNuYXBzaG90IHJlamVjdGlvbiAoNDEyKSBtZWFucyB0aGUgcmVwbGF5J3MgZXZlbnQgbG9nIHdhcyBtaXNzaW5nIGFuXG4vLyBldmVudCB0aGUgV29ybGQgaGFkIGFscmVhZHkgcmVjb3JkZWQsIHNvIHRoZSByZXBsYXkgaXMgcmUtZGVyaXZlZCBmcm9tIGFcbi8vIGNvcnJlY3RlZCBsb2cgaW5zaWRlIHRoZSBzYW1lIGludm9jYXRpb24uIEJvdW5kZWQgYmVjYXVzZSBhIHBlcnNpc3RlbnRseVxuLy8gcmVqZWN0ZWQgd3JpdGUgc2hvdWxkIGVzY2FsYXRlIHJhdGhlciB0aGFuIHNwaW46IGFmdGVyIHRoaXMgbWFueSByZXN0YXJ0cyB0aGVcbi8vIHJ1biBpcyByZS1pbnZva2VkIChhIG5ldyBpbnZvY2F0aW9uLCBwb3NzaWJseSBpbiBhIGRpZmZlcmVudCByZWdpb24pLCBhbmQgdGhlXG4vLyBydW4tbGV2ZWwgYnVkZ2V0IGJlbG93IHRoZW4gYXBwbGllcy5cbmV4cG9ydCBjb25zdCBQUkVDT05ESVRJT05fTUFYX0lOUFJPQ0VTU19SRVNUQVJUUyA9IDM7XG5cbi8qKlxuICogRWZmZWN0aXZlIGluLXByb2Nlc3MgcmVwbGF5LXJlc3RhcnQgYnVkZ2V0IGZvciBzdGFsZS1zbmFwc2hvdCByZWplY3Rpb25zLlxuICogT3ZlcnJpZGUgdmlhIGBXT1JLRkxPV19QUkVDT05ESVRJT05fTUFYX0lOUFJPQ0VTU19SRVNUQVJUU2AuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRQcmVjb25kaXRpb25NYXhJblByb2Nlc3NSZXN0YXJ0cygpOiBudW1iZXIge1xuICByZXR1cm4gZW52TnVtYmVyKFxuICAgICdXT1JLRkxPV19QUkVDT05ESVRJT05fTUFYX0lOUFJPQ0VTU19SRVNUQVJUUycsXG4gICAgUFJFQ09ORElUSU9OX01BWF9JTlBST0NFU1NfUkVTVEFSVFMsXG4gICAgeyBpbnRlZ2VyOiB0cnVlIH1cbiAgKTtcbn1cblxuLy8gVGhlIGluLXByb2Nlc3MgYnVkZ2V0IGFib3ZlIGlzIHBlci1pbnZvY2F0aW9uLCBhbmQgYSByZS1pbnZvY2F0aW9uIHRoYXRcbi8vIGVucXVldWVzIGEgZnJlc2ggbWVzc2FnZSBhbHNvIHJlc3RhcnRzIHRoZSBxdWV1ZSdzIGRlbGl2ZXJ5IGNvdW50LCBzbyB3aXRob3V0XG4vLyBhIGNvdW50ZXIgY2FycmllZCBvbiB0aGUgbWVzc2FnZSBhIHBlcm1hbmVudGx5IGZlbmNlZCBydW4gaGFzIG5vIHJ1bi1sZXZlbFxuLy8gYm91bmQgYXQgYWxsLiBJdCBjYW4gc3RheSBmZW5jZWQgd2l0aG91dCBhbnkgcGVybWFuZW50IGZhdWx0IOKAlCBhIGZ1bGwgcmVsb2FkXG4vLyBpcyBub3QgYXRvbWljIGFjcm9zcyBwYWdlcywgc28gYSBidXN5IHJ1biBjYW4gYWNxdWlyZSBhIG5ldyBob2xlIG9uIGV2ZXJ5XG4vLyByZWxvYWQg4oCUIHNvIHRoZSBjaGFpbiBpcyBjb3VudGVkIGFuZCB0aGUgcnVuIGZhaWxzIG9uY2UgdGhpcyBtYW55XG4vLyByZS1pbnZvY2F0aW9ucyBoYXZlIGJlZW4gc3BlbnQgb24gc3RhbGUtc25hcHNob3QgcmVqZWN0aW9ucy5cbmV4cG9ydCBjb25zdCBQUkVDT05ESVRJT05fTUFYX1JFSU5WT0NBVElPTlMgPSA1O1xuXG4vKipcbiAqIEVmZmVjdGl2ZSBwZXItcnVuIGJ1ZGdldCBmb3IgcmUtaW52b2NhdGlvbnMgY2F1c2VkIGJ5IHN0YWxlLXNuYXBzaG90XG4gKiByZWplY3Rpb25zLiBPdmVycmlkZSB2aWEgYFdPUktGTE9XX1BSRUNPTkRJVElPTl9NQVhfUkVJTlZPQ0FUSU9OU2AuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRQcmVjb25kaXRpb25NYXhSZWludm9jYXRpb25zKCk6IG51bWJlciB7XG4gIHJldHVybiBlbnZOdW1iZXIoXG4gICAgJ1dPUktGTE9XX1BSRUNPTkRJVElPTl9NQVhfUkVJTlZPQ0FUSU9OUycsXG4gICAgUFJFQ09ORElUSU9OX01BWF9SRUlOVk9DQVRJT05TLFxuICAgIHsgaW50ZWdlcjogdHJ1ZSB9XG4gICk7XG59XG5cbi8vIEJhY2tvZmYgYmVmb3JlIGEgcHJlY29uZGl0aW9uIHJlLWludm9jYXRpb24uIFVubGlrZSB0aGUgaW4tcHJvY2VzcyByZXN0YXJ0XG4vLyAod2hlcmUgdGhlIHBvaW50IGlzIHRvIHJlLXJlYWQgaW1tZWRpYXRlbHkpLCBhIHJlLWludm9jYXRpb24gb25seSBoYXBwZW5zXG4vLyBhZnRlciB0aGUgaW4tcHJvY2VzcyBidWRnZXQgZmFpbGVkIHRvIGNhdGNoIHVwLCBzbyB0aGUgbG9nIGlzIGJlaW5nIGV4dGVuZGVkXG4vLyBmYXN0ZXIgdGhhbiB0aGlzIHJlcGxheSBjYW4gZm9sbG93IGl0LiBXYWl0aW5nIGxldHMgdGhlIHdyaXRlcnMgcXVpZXNjZS5cbmV4cG9ydCBjb25zdCBQUkVDT05ESVRJT05fUkVJTlZPS0VfREVMQVlfU0VDT05EUyA9IDI7XG5cbi8qKlxuICogRWZmZWN0aXZlIGRlbGF5IGJlZm9yZSBhIHByZWNvbmRpdGlvbiByZS1pbnZvY2F0aW9uLiBPdmVycmlkZSB2aWFcbiAqIGBXT1JLRkxPV19QUkVDT05ESVRJT05fUkVJTlZPS0VfREVMQVlfU0VDT05EU2AuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRQcmVjb25kaXRpb25SZWludm9rZURlbGF5U2Vjb25kcygpOiBudW1iZXIge1xuICByZXR1cm4gZW52TnVtYmVyKFxuICAgICdXT1JLRkxPV19QUkVDT05ESVRJT05fUkVJTlZPS0VfREVMQVlfU0VDT05EUycsXG4gICAgUFJFQ09ORElUSU9OX1JFSU5WT0tFX0RFTEFZX1NFQ09ORFMsXG4gICAgeyBpbnRlZ2VyOiB0cnVlIH1cbiAgKTtcbn1cblxuLy8gQSBkZWxpdmVyeSByZWFjaGluZyBhIGRlcGxveW1lbnQgdGhlIHJ1biBpcyBub3QgcGlubmVkIHRvIGlzIG5vdCB0cmVhdGVkIGFzXG4vLyBwZXJtYW5lbnQuIFJlLXJvdXRlIHRoZSBtZXNzYWdlIGF0IHRoZSBydW4ncyBvd24gZGVwbG95bWVudCBhIGJvdW5kZWQgbnVtYmVyXG4vLyBvZiB0aW1lcyBiZWZvcmUgZmFpbGluZyB0aGUgcnVuIHdpdGggREVQTE9ZTUVOVF9NSVNNQVRDSC5cbmV4cG9ydCBjb25zdCBERVBMT1lNRU5UX01JU01BVENIX01BWF9SRVRSSUVTID0gMztcblxuLyoqXG4gKiBFZmZlY3RpdmUgZGVwbG95bWVudC1taXNtYXRjaCByZS1yb3V0ZSBidWRnZXQuIE92ZXJyaWRlIHZpYVxuICogYFdPUktGTE9XX0RFUExPWU1FTlRfTUlTTUFUQ0hfTUFYX1JFVFJJRVNgOyBgMGAgZmFpbHMgdGhlIHJ1biBvbiB0aGUgZmlyc3RcbiAqIG1pc3JvdXRlZCBkZWxpdmVyeSBpbnN0ZWFkIG9mIGF0dGVtcHRpbmcgcmVjb3ZlcnkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXREZXBsb3ltZW50TWlzbWF0Y2hNYXhSZXRyaWVzKCk6IG51bWJlciB7XG4gIHJldHVybiBlbnZOdW1iZXIoXG4gICAgJ1dPUktGTE9XX0RFUExPWU1FTlRfTUlTTUFUQ0hfTUFYX1JFVFJJRVMnLFxuICAgIERFUExPWU1FTlRfTUlTTUFUQ0hfTUFYX1JFVFJJRVMsXG4gICAgeyBpbnRlZ2VyOiB0cnVlLCBtaW46IDAgfVxuICApO1xufVxuIl19
|
|
511
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bnRpbWUvY29uc3RhbnRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNsRCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDNUMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUU3Qyw0RUFBNEU7QUFDNUUsNEVBQTRFO0FBQzVFLHlFQUF5RTtBQUN6RSxvREFBb0Q7QUFDcEQsRUFBRTtBQUNGLCtFQUErRTtBQUMvRSxzREFBc0Q7QUFDdEQsK0VBQStFO0FBQy9FLDRFQUE0RTtBQUM1RSw2RUFBNkU7QUFDN0UseUVBQXlFO0FBQ3pFLCtFQUErRTtBQUMvRSw2RUFBNkU7QUFDN0UsK0VBQStFO0FBQy9FLGdGQUFnRjtBQUNoRiwyRUFBMkU7QUFDM0UseUVBQXlFO0FBQ3pFLDZCQUE2QjtBQUM3QixNQUFNLENBQUMsTUFBTSxvQkFBb0IsR0FBRyxFQUFFLENBQUM7QUFFdkM7O0dBRUc7QUFDSCxNQUFNLFVBQVUscUJBQXFCO0lBQ25DLHdFQUF3RTtJQUN4RSwwRUFBMEU7SUFDMUUsOEVBQThFO0lBQzlFLHlFQUF5RTtJQUN6RSw0RUFBNEU7SUFDNUUsT0FBTyxTQUFTLENBQUMsK0JBQStCLEVBQUUsb0JBQW9CLEVBQUU7UUFDdEUsT0FBTyxFQUFFLElBQUk7UUFDYixHQUFHLEVBQUUsQ0FBQztRQUNOLEdBQUcsRUFBRSxvQkFBb0I7S0FDMUIsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FxQkc7QUFDSCxNQUFNLENBQUMsTUFBTSxpQkFBaUIsR0FBRyxPQUFPLENBQUM7QUFFekMsMkRBQTJEO0FBQzNELE1BQU0sQ0FBQyxNQUFNLHFCQUFxQixHQUFHLE1BQU0sQ0FBQztBQUU1Qzs7OztHQUlHO0FBQ0gs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QUMsQ0FBQztBQUVyRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsbUNBQW1DO0lBQ2pELE9BQU8sU0FBUyxDQUNkLDhDQUE4QyxFQUM5QyxtQ0FBbUMsRUFDbkMsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQ2xCLENBQUM7QUFDSixDQUFDO0FBRUQsOEVBQThFO0FBQzlFLCtFQUErRTtBQUMvRSw0REFBNEQ7QUFDNUQsTUFBTSxDQUFDLE1BQU0sK0JBQStCLEdBQUcsQ0FBQyxDQUFDO0FBRWpEOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUsK0JBQStCO0lBQzdDLE9BQU8sU0FBUyxDQUNkLDBDQUEwQyxFQUMxQywrQkFBK0IsRUFDL0IsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsQ0FDMUIsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBnbG9iYWxTaW5nbGV0b24gfSBmcm9tICdAd29ya2Zsb3cvdXRpbHMnO1xuaW1wb3J0IHsgZW52TnVtYmVyIH0gZnJvbSAnQHdvcmtmbG93L3dvcmxkJztcbmltcG9ydCB7IHJ1bnRpbWVMb2dnZXIgfSBmcm9tICcuLi9sb2dnZXIuanMnO1xuXG4vLyBNYXhpbXVtIG51bWJlciBvZiBxdWV1ZSBkZWxpdmVyeSBhdHRlbXB0cyBiZWZvcmUgdGhlIGhhbmRsZXIgZ2l2ZXMgdXAgYW5kXG4vLyBncmFjZWZ1bGx5IGZhaWxzIHRoZSBydW4vc3RlcC4gVGhpcyBtdXN0IGJlIGJvdW5kZWQgdW5kZXIgdGhlIFZRUyBtZXNzYWdlXG4vLyBtYXggdmlzaWJpbGl0eSB3aW5kb3cgKDI0IGhvdXJzKSBzbyB0aGF0IG91ciBoYW5kbGVyLXNpZGUgZmFpbHVyZSBwYXRoXG4vLyByZWxpYWJseSBleGVjdXRlcyBiZWZvcmUgVlFTIGV4cGlyZXMgdGhlIG1lc3NhZ2UuXG4vL1xuLy8gVGhlIGVmZmVjdGl2ZSB3YWxsLWNsb2NrIHN1cnZpdmFsIGRlcGVuZHMgb24gdGhlIHBlci1yZWRlbGl2ZXJ5IGJhY2tvZmY6IHRoZVxuLy8gYHJldHJ5LWFmdGVyYCB0aGUgaGFuZGxlciByZXR1cm5zIChzZWUgd29ybGQtdmVyY2VsXG4vLyBgZ2V0SGFuZGxlckVycm9yUmV0cnlBZnRlclNlY29uZHNgKSBmZWQgdGhyb3VnaCBWUVMgYGNhbGN1bGF0ZUJhY2tvZmZEZWxheWAuXG4vLyBWUVMgdXNlcyBvdXIgdmFsdWUgZm9yIHRoZSBmaXJzdCAzMiBhdHRlbXB0cyAoY2xhbXBlZCB0byBbNXMsIDkwMHNdKSB0aGVuXG4vLyBhcHBsaWVzIGl0cyBvd24gZXhwb25lbnRpYWwgZ3Jvd3RoLCBldmVyeSBob3AgaGFyZC1jYXBwZWQgYXQgdGhlIFNRUyBsaW1pdFxuLy8gb2YgOTAwcy4gV2l0aCB0aGUgYmFja29mZiByYW1waW5nIHRvd2FyZCB0aGF0IDkwMHMgY2VpbGluZyAocmVhY2hlZCBieVxuLy8gfmRlbGl2ZXJ5IDExKSwgNDggYXR0ZW1wdHMgc3BhbiByb3VnaGx5IDnigJMxMCBob3VycyBvZiB3YWxsLWNsb2NrICh+MzUsMDAwcyksXG4vLyBjb21mb3J0YWJseSB1bmRlciB0aGUgMjQtaG91ciBtZXNzYWdlLXZpc2liaWxpdHkgbGltaXQgc28gdGhlIGZhaWx1cmUgcGF0aFxuLy8gcnVucyBiZWZvcmUgdGhlIG1lc3NhZ2UgZXhwaXJlcy4gKEEgZmxhdHRlciwgbG93LWNhcHBlZCBiYWNrb2ZmIGV4aGF1c3RzIHRoZVxuLy8gYnVkZ2V0IGluIG9ubHkgYSBmZXcgaG91cnMsIGZhaWxpbmcgb3RoZXJ3aXNlLWhlYWx0aHkgcnVucyBkdXJpbmcgYSB0cmFuc2llbnRcbi8vIGJhY2tlbmQgb3V0YWdlOyBjb252ZXJzZWx5LCBzcGFubmluZyB0aGUgZnVsbCAyNGggd2luZG93IHdvdWxkIHJlcXVpcmUgYVxuLy8gc3Vic3RhbnRpYWxseSBoaWdoZXIgY2FwIGhlcmUsIG5vdCBhIGhpZ2hlciBwZXItaG9wIGNlaWxpbmcsIHNpbmNlIFZRU1xuLy8gY2xhbXBzIGV2ZXJ5IGhvcCBhdCA5MDBzLilcbmV4cG9ydCBjb25zdCBNQVhfUVVFVUVfREVMSVZFUklFUyA9IDQ4O1xuXG4vKipcbiAqIEVmZmVjdGl2ZSBtYXggcXVldWUgZGVsaXZlcmllcy4gT3ZlcnJpZGUgdmlhIGBXT1JLRkxPV19NQVhfUVVFVUVfREVMSVZFUklFU2AuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRNYXhRdWV1ZURlbGl2ZXJpZXMoKTogbnVtYmVyIHtcbiAgLy8gT25seSBldmVyIGxvd2VyIHRoZSBkZWxpdmVyeSBidWRnZXQuIFRoZSBkZWZhdWx0IGlzIGNhbGlicmF0ZWQgc28gdGhlXG4gIC8vIGhhbmRsZXItc2lkZSBmYWlsdXJlIHBhdGggcnVucyBiZWZvcmUgVlFTIG1lc3NhZ2UtcmV0ZW50aW9uIGV4cGlyeSAoc2VlXG4gIC8vIE1BWF9RVUVVRV9ERUxJVkVSSUVTIGFib3ZlKTsgYSBoaWdoZXIgdmFsdWUgd291bGQgYnlwYXNzIHRoYXQgaW52YXJpYW50IGFuZFxuICAvLyBsZXQgYSBiYWQgZGVwbG95bWVudCByZWRlbGl2ZXIgdW50aWwgcXVldWUgZXhwaXJ5IGluc3RlYWQgb2YgcmVjb3JkaW5nXG4gIC8vIHJ1bl9mYWlsLiBgbWF4YCBjbGFtcHMgYSB0b28taGlnaCBvdmVycmlkZSBiYWNrIGRvd24gdG8gdGhlIHNhZmUgZGVmYXVsdC5cbiAgcmV0dXJuIGVudk51bWJlcignV09SS0ZMT1dfTUFYX1FVRVVFX0RFTElWRVJJRVMnLCBNQVhfUVVFVUVfREVMSVZFUklFUywge1xuICAgIGludGVnZXI6IHRydWUsXG4gICAgbWluOiAxLFxuICAgIG1heDogTUFYX1FVRVVFX0RFTElWRVJJRVMsXG4gIH0pO1xufVxuXG4vKipcbiAqIERlZmF1bHQgbWF4aW11bSB0aW1lIGFsbG93ZWQgZm9yIHRoZSAqcmVwbGF5KiBwb3J0aW9uIG9mIGEgc2luZ2xlIHdvcmtmbG93XG4gKiBoYW5kbGVyIGludm9jYXRpb24gKGluIG1zKS4gVGhpcyBidWRnZXQgb25seSBjb3ZlcnMgZGV0ZXJtaW5pc3RpYy1yZXBsYXlcbiAqIGFuZCB3b3JrZmxvdy1WTSBleGVjdXRpb24gYmV0d2VlbiBzdGVwIGJvdW5kYXJpZXMuIElubGluZSBzdGVwIGJvZGllc1xuICogKGBcInVzZSBzdGVwXCJgIGZ1bmN0aW9ucyBpbnZva2VkIHZpYSBgZXhlY3V0ZVN0ZXBgKSBkbyBOT1QgY291bnQgYWdhaW5zdFxuICogaXQuIFN0ZXAgYm9kaWVzIGFyZSBib3VuZGVkIHNlcGFyYXRlbHkgYnkgdGhlIHBsYXRmb3JtJ3MgZnVuY3Rpb25cbiAqIGBtYXhEdXJhdGlvbmAgKGUuZy4gODAwcyBvbiBWZXJjZWwgUHJvIEZsdWlkKSBhbmQgYE5PX0lOTElORV9SRVBMQVlfQUZURVJfTVNgLlxuICpcbiAqIElmIHRoZSBub24tc3RlcCAoXCJyZXBsYXlcIikgdGltZSB3aXRoaW4gYSBzaW5nbGUgaW52b2NhdGlvbiBleGNlZWRzIHRoaXNcbiAqIGJ1ZGdldCwgdGhlIGhhbmRsZXIgcmVqZWN0cyBzbyB0aGUgcXVldWUgY2FuIHJldHJ5LiBBZnRlclxuICogYFJFUExBWV9USU1FT1VUX01BWF9SRVRSSUVTYCBleGhhdXN0ZWQgYXR0ZW1wdHMgdGhlIHJ1biBpcyBmYWlsZWQgd2l0aFxuICogYFJVTl9FUlJPUl9DT0RFUy5SRVBMQVlfVElNRU9VVGAuXG4gKlxuICogTm90ZSB0aGF0IG9uIFZlcmNlbCBIb2JieSAoc3RhbmRhcmQgZnVuY3Rpb25zKSwgdGhlIHBsYXRmb3JtIGBtYXhEdXJhdGlvbmBcbiAqIGlzIDYwcywgd2VsbCBiZWxvdyB0aGlzIGJ1ZGdldCwgc28gdGhlIHBsYXRmb3JtIFNJR1RFUk0gd2lsbCBmaXJlIGZpcnN0XG4gKiBhbmQgdGhlIHF1ZXVlIHdpbGwgcmUtZGVsaXZlciB1bnRpbCB0aGUgdmlzaWJpbGl0eSB3aW5kb3cgZXhwaXJlcy4gV2l0aFxuICogRmx1aWQgQ29tcHV0ZSBvbiBIb2JieSB0aGUgcGVyLWZ1bmN0aW9uIGNlaWxpbmcgcmlzZXMgdG8gMzAwcywgc3RpbGxcbiAqIHVuZGVyIHRoZSBkZWZhdWx0IGJ1ZGdldC5cbiAqXG4gKiBPdmVycmlkZSB2aWEgdGhlIGBXT1JLRkxPV19SRVBMQVlfVElNRU9VVF9NU2AgZW52IHZhciAoY2xhbXBlZCB0b1xuICogYE1JTl9SRVBMQVlfVElNRU9VVF9NU2AuLmBNQVhfUkVQTEFZX1RJTUVPVVRfTVNgKS5cbiAqL1xuZXhwb3J0IGNvbnN0IFJFUExBWV9USU1FT1VUX01TID0gMjQwXzAwMDtcblxuLyoqIExvd2VyIGJvdW5kIGZvciB0aGUgcmVwbGF5LXRpbWVvdXQgZW52IHZhciBvdmVycmlkZS4gKi9cbmV4cG9ydCBjb25zdCBNSU5fUkVQTEFZX1RJTUVPVVRfTVMgPSAzMF8wMDA7XG5cbi8qKlxuICogVXBwZXIgYm91bmQgZm9yIHRoZSByZXBsYXktdGltZW91dCBlbnYgdmFyIG92ZXJyaWRlLiA3ODBzIGxlYXZlcyDiiaUyMHMgb2ZcbiAqIGhlYWRyb29tIHVuZGVyIFZlcmNlbCBQcm8gRmx1aWQncyA4MDBzIGZ1bmN0aW9uIGNlaWxpbmcgc28gdGhlIGhhbmRsZXJcbiAqIGNhbiB3cml0ZSBgcnVuX2ZhaWxlZGAgYmVmb3JlIFNJR1RFUk0uXG4gKi9cbmV4cG9ydCBjb25zdCBNQVhfUkVQTEFZX1RJTUVPVVRfTVMgPSA3ODBfMDAwO1xuXG4vLyBUcmFjayB3aGljaCByYXcgZW52IHZhciB2YWx1ZXMgd2UndmUgYWxyZWFkeSB3YXJuZWQgYWJvdXQgc28gdGhlIHdhcm5pbmdcbi8vIGxvZyBvbmx5IGZpcmVzIG9uY2UgcGVyIHByb2Nlc3MgKHRoZSBmdW5jdGlvbiBtYXkgYmUgY2FsbGVkIG1hbnkgdGltZXMpLlxuLy9cbi8vIE9uIGBnbG9iYWxUaGlzYCByYXRoZXIgdGhhbiBhdCBtb2R1bGUgc2NvcGUgc28gXCJvbmNlIHBlciBwcm9jZXNzXCIgc3Vydml2ZXNcbi8vIGJ1bmRsaW5nOiB0aGlzIHBhY2thZ2UgaXMgY29tcGlsZWQgaW50byB0aGUgaG9zdCBhcHBsaWNhdGlvbidzIHNlcnZlciBidWlsZFxuLy8gb25jZSBwZXIgYnVuZGxlciBsYXllciwgYW5kIHBlci1jb3B5IHNldHMgd2FybiBvbmNlIHBlciBsYXllciBpbnN0ZWFkLlxuY29uc3Qgd2FybmVkID0gZ2xvYmFsU2luZ2xldG9uKCdAd29ya2Zsb3cvY29yZS8vZW52V2FybmluZ3MnLCAxLCAoKSA9PiAoe1xuICByZXBsYXlUaW1lb3V0VmFsdWVzOiBuZXcgU2V0PHN0cmluZz4oKSxcbiAgbWF4SW5saW5lU3RlcHNWYWx1ZXM6IG5ldyBTZXQ8c3RyaW5nPigpLFxuICBtYXhFdmVudHNWYWx1ZXM6IG5ldyBTZXQ8c3RyaW5nPigpLFxufSkpO1xuXG5mdW5jdGlvbiB3YXJuT25jZShcbiAgcmF3OiBzdHJpbmcsXG4gIG1lc3NhZ2U6IHN0cmluZyxcbiAgZGF0YTogUmVjb3JkPHN0cmluZywgdW5rbm93bj5cbik6IHZvaWQge1xuICBpZiAod2FybmVkLnJlcGxheVRpbWVvdXRWYWx1ZXMuaGFzKHJhdykpIHJldHVybjtcbiAgd2FybmVkLnJlcGxheVRpbWVvdXRWYWx1ZXMuYWRkKHJhdyk7XG4gIHJ1bnRpbWVMb2dnZXIud2FybihtZXNzYWdlLCBkYXRhKTtcbn1cblxuLyoqXG4gKiBSZXNvbHZlIHRoZSBlZmZlY3RpdmUgcmVwbGF5LXRpbWVvdXQgYnVkZ2V0IGZvciB0aGUgY3VycmVudCBwcm9jZXNzLlxuICpcbiAqIFJlYWRzIGBwcm9jZXNzLmVudi5XT1JLRkxPV19SRVBMQVlfVElNRU9VVF9NU2AgbGF6aWx5IHNvIHRlc3RzIGFuZFxuICogZGVwbG95bWVudHMgY2FuIG92ZXJyaWRlIHBlciBpbnZvY2F0aW9uLiBJbnZhbGlkIC8gb3V0LW9mLXJhbmdlIHZhbHVlc1xuICogZmFsbCBiYWNrIHRvIGEgc2FmZSB2YWx1ZSAobm8gdGhyb3c6IHRoZSBlbnYgdmFyIGlzIGFuIGVzY2FwZSBoYXRjaCxcbiAqIG5vdCBhIGhhcmQgcmVxdWlyZW1lbnQpIGFuZCBlbWl0IGEgb25lLXRpbWUgd2FybmluZyBzbyBtaXNjb25maWd1cmF0aW9uXG4gKiBpcyBvYnNlcnZhYmxlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0UmVwbGF5VGltZW91dE1zKCk6IG51bWJlciB7XG4gIGNvbnN0IHJhdyA9IHByb2Nlc3MuZW52LldPUktGTE9XX1JFUExBWV9USU1FT1VUX01TO1xuICBpZiAoIXJhdykgcmV0dXJuIFJFUExBWV9USU1FT1VUX01TO1xuICBjb25zdCBwYXJzZWQgPSBOdW1iZXIocmF3KTtcbiAgaWYgKCFOdW1iZXIuaXNGaW5pdGUocGFyc2VkKSB8fCBwYXJzZWQgPD0gMCkge1xuICAgIHdhcm5PbmNlKFxuICAgICAgcmF3LFxuICAgICAgJ0lnbm9yaW5nIFdPUktGTE9XX1JFUExBWV9USU1FT1VUX01TOiBub3QgYSBwb3NpdGl2ZSBmaW5pdGUgbnVtYmVyOyB1c2luZyBkZWZhdWx0JyxcbiAgICAgIHsgcmF3LCBkZWZhdWx0TXM6IFJFUExBWV9USU1FT1VUX01TIH1cbiAgICApO1xuICAgIHJldHVybiBSRVBMQVlfVElNRU9VVF9NUztcbiAgfVxuICBpZiAocGFyc2VkIDwgTUlOX1JFUExBWV9USU1FT1VUX01TKSB7XG4gICAgd2Fybk9uY2UocmF3LCAnV09SS0ZMT1dfUkVQTEFZX1RJTUVPVVRfTVMgYmVsb3cgbWluaW11bTsgY2xhbXBlZCcsIHtcbiAgICAgIHJhdyxcbiAgICAgIGNsYW1wZWRNczogTUlOX1JFUExBWV9USU1FT1VUX01TLFxuICAgICAgbWluTXM6IE1JTl9SRVBMQVlfVElNRU9VVF9NUyxcbiAgICB9KTtcbiAgICByZXR1cm4gTUlOX1JFUExBWV9USU1FT1VUX01TO1xuICB9XG4gIGlmIChwYXJzZWQgPiBNQVhfUkVQTEFZX1RJTUVPVVRfTVMpIHtcbiAgICB3YXJuT25jZShyYXcsICdXT1JLRkxPV19SRVBMQVlfVElNRU9VVF9NUyBhYm92ZSBtYXhpbXVtOyBjbGFtcGVkJywge1xuICAgICAgcmF3LFxuICAgICAgY2xhbXBlZE1zOiBNQVhfUkVQTEFZX1RJTUVPVVRfTVMsXG4gICAgICBtYXhNczogTUFYX1JFUExBWV9USU1FT1VUX01TLFxuICAgIH0pO1xuICAgIHJldHVybiBNQVhfUkVQTEFZX1RJTUVPVVRfTVM7XG4gIH1cbiAgcmV0dXJuIHBhcnNlZDtcbn1cblxuLyoqXG4gKiBSZXNldCB0aGUgd2Fybi1vbmNlIGNhY2hlLiBUZXN0LW9ubHk6IGV4cG9ydGVkIHNvIHVuaXQgdGVzdHMgY2FuXG4gKiBleGVyY2lzZSB0aGUgd2FybiBwYXRoIHJlcGVhdGVkbHkgd2l0aG91dCBzaGFyaW5nIHN0YXRlLlxuICpcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gX3Jlc2V0UmVwbGF5VGltZW91dFdhcm5DYWNoZUZvclRlc3RzKCk6IHZvaWQge1xuICB3YXJuZWQucmVwbGF5VGltZW91dFZhbHVlcy5jbGVhcigpO1xufVxuXG4vLyBOdW1iZXIgb2YgcXVldWUgZGVsaXZlcnkgYXR0ZW1wdHMgdG8gYWxsb3cgYmVmb3JlIHBlcm1hbmVudGx5IGZhaWxpbmcgYSBydW5cbi8vIGR1ZSB0byBhIHJlcGxheSB0aW1lb3V0LiBPbiBhdHRlbXB0cyAxIHRocm91Z2ggdGhpcyB2YWx1ZSwgdGhlIHRpbWVvdXRcbi8vIGhhbmRsZXIgcmVqZWN0cyB3aXRob3V0IHdyaXRpbmcgcnVuX2ZhaWxlZCBzbyB0aGUgcXVldWUgcmV0cmllcyB0aGUgbWVzc2FnZS5cbi8vIE9uIHRoZSBuZXh0IGF0dGVtcHQgdGhlIHJ1biBpcyBtYXJrZWQgYXMgZmFpbGVkLlxuZXhwb3J0IGNvbnN0IFJFUExBWV9USU1FT1VUX01BWF9SRVRSSUVTID0gMztcblxuLyoqXG4gKiBFZmZlY3RpdmUgcmVwbGF5LXRpbWVvdXQgcmV0cnkgYnVkZ2V0LiBPdmVycmlkZSB2aWFcbiAqIGBXT1JLRkxPV19SRVBMQVlfVElNRU9VVF9NQVhfUkVUUklFU2AuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRSZXBsYXlUaW1lb3V0TWF4UmV0cmllcygpOiBudW1iZXIge1xuICByZXR1cm4gZW52TnVtYmVyKFxuICAgICdXT1JLRkxPV19SRVBMQVlfVElNRU9VVF9NQVhfUkVUUklFUycsXG4gICAgUkVQTEFZX1RJTUVPVVRfTUFYX1JFVFJJRVMsXG4gICAgeyBpbnRlZ2VyOiB0cnVlIH1cbiAgKTtcbn1cblxuLyoqXG4gKiBEZWZhdWx0IG1heGltdW0gbnVtYmVyIG9mIHN0ZXBzIHRoZSBvd25lZC1pbmxpbmUgcGF0aCBydW5zIGlubGluZSAoaW5cbiAqIHBhcmFsbGVsKSBwZXIgc3VzcGVuc2lvbi4gVGhlIHJlc3QgYXJlIHF1ZXVlZCB0byBiYWNrZ3JvdW5kIGhhbmRsZXJzLiBFYWNoXG4gKiBpbmxpbmUgc3RlcCBpcyBjcmVhdGVkIGxhemlseSAoaXRzIGBzdGVwX2NyZWF0ZWRgIGlzIGZvbGRlZCBpbnRvIHRoZVxuICogYHN0ZXBfc3RhcnRlZGAgdGhhdCBgZXhlY3V0ZVN0ZXBgIHNlbmRzKSwgc28gaW5saW5pbmcgTiBzdGVwcyBzYXZlcyBOIHF1ZXVlXG4gKiByb3VuZC10cmlwcyBmb3IgYSBgUHJvbWlzZS5hbGxgLXN0eWxlIGZhbi1vdXQuIGAxYCByZXByb2R1Y2VzIHRoZVxuICogc2luZ2xlLWlubGluZS1zdGVwIGJlaGF2aW9yIGV4YWN0bHkgKHVzZWZ1bCBraWxsLXN3aXRjaCkuXG4gKlxuICogT3ZlcnJpZGUgdmlhIGBXT1JLRkxPV19NQVhfSU5MSU5FX1NURVBTYCAoY2xhbXBlZCB0b1xuICogYE1JTl9NQVhfSU5MSU5FX1NURVBTYC4uYE1BWF9NQVhfSU5MSU5FX1NURVBTYCkuXG4gKi9cbmV4cG9ydCBjb25zdCBNQVhfSU5MSU5FX1NURVBTID0gMztcblxuLyoqIExvd2VyIGJvdW5kIGZvciB0aGUgaW5saW5lLXN0ZXBzIGVudiBvdmVycmlkZSAoMSA9IHNpbmdsZSBpbmxpbmUgc3RlcCkuICovXG5leHBvcnQgY29uc3QgTUlOX01BWF9JTkxJTkVfU1RFUFMgPSAxO1xuXG4vKipcbiAqIFVwcGVyIGJvdW5kIGZvciB0aGUgaW5saW5lLXN0ZXBzIGVudiBvdmVycmlkZS4gSW5saW5lIGJvZGllcyBydW4gaW4gcGFyYWxsZWxcbiAqIHdpdGhpbiBvbmUgZnVuY3Rpb24gaW52b2NhdGlvbiwgc28gdGhpcyBjYXBzIG1lbW9yeS9DUFUgZmFuLW91dCBwZXIgaGFuZGxlci5cbiAqL1xuZXhwb3J0IGNvbnN0IE1BWF9NQVhfSU5MSU5FX1NURVBTID0gMTY7XG5cbi8qKlxuICogUmVzb2x2ZSB0aGUgZWZmZWN0aXZlIG1heCBudW1iZXIgb2YgaW5saW5lIHN0ZXBzIGZvciB0aGUgY3VycmVudCBwcm9jZXNzLlxuICpcbiAqIFJlYWRzIGBwcm9jZXNzLmVudi5XT1JLRkxPV19NQVhfSU5MSU5FX1NURVBTYCBsYXppbHkgc28gdGVzdHMgYW5kXG4gKiBkZXBsb3ltZW50cyBjYW4gb3ZlcnJpZGUgcGVyIGludm9jYXRpb24uIEludmFsaWQgLyBvdXQtb2YtcmFuZ2UgdmFsdWVzIGZhbGxcbiAqIGJhY2sgdG8gYSBzYWZlIHZhbHVlIChubyB0aHJvdzogdGhlIGVudiB2YXIgaXMgYW4gZXNjYXBlIGhhdGNoKSBhbmQgZW1pdCBhXG4gKiBvbmUtdGltZSB3YXJuaW5nIHNvIG1pc2NvbmZpZ3VyYXRpb24gaXMgb2JzZXJ2YWJsZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldE1heElubGluZVN0ZXBzKCk6IG51bWJlciB7XG4gIGNvbnN0IHJhdyA9IHByb2Nlc3MuZW52LldPUktGTE9XX01BWF9JTkxJTkVfU1RFUFM7XG4gIGlmICghcmF3KSByZXR1cm4gTUFYX0lOTElORV9TVEVQUztcbiAgY29uc3QgcGFyc2VkID0gTnVtYmVyKHJhdyk7XG4gIGlmICghTnVtYmVyLmlzSW50ZWdlcihwYXJzZWQpIHx8IHBhcnNlZCA8PSAwKSB7XG4gICAgaWYgKCF3YXJuZWQubWF4SW5saW5lU3RlcHNWYWx1ZXMuaGFzKHJhdykpIHtcbiAgICAgIHdhcm5lZC5tYXhJbmxpbmVTdGVwc1ZhbHVlcy5hZGQocmF3KTtcbiAgICAgIHJ1bnRpbWVMb2dnZXIud2FybihcbiAgICAgICAgJ0lnbm9yaW5nIFdPUktGTE9XX01BWF9JTkxJTkVfU1RFUFM6IG5vdCBhIHBvc2l0aXZlIGludGVnZXI7IHVzaW5nIGRlZmF1bHQnLFxuICAgICAgICB7IHJhdywgZGVmYXVsdFZhbHVlOiBNQVhfSU5MSU5FX1NURVBTIH1cbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBNQVhfSU5MSU5FX1NURVBTO1xuICB9XG4gIGlmIChwYXJzZWQgPCBNSU5fTUFYX0lOTElORV9TVEVQUykgcmV0dXJuIE1JTl9NQVhfSU5MSU5FX1NURVBTO1xuICBpZiAocGFyc2VkID4gTUFYX01BWF9JTkxJTkVfU1RFUFMpIHtcbiAgICBpZiAoIXdhcm5lZC5tYXhJbmxpbmVTdGVwc1ZhbHVlcy5oYXMocmF3KSkge1xuICAgICAgd2FybmVkLm1heElubGluZVN0ZXBzVmFsdWVzLmFkZChyYXcpO1xuICAgICAgcnVudGltZUxvZ2dlci53YXJuKCdXT1JLRkxPV19NQVhfSU5MSU5FX1NURVBTIGFib3ZlIG1heGltdW07IGNsYW1wZWQnLCB7XG4gICAgICAgIHJhdyxcbiAgICAgICAgY2xhbXBlZFZhbHVlOiBNQVhfTUFYX0lOTElORV9TVEVQUyxcbiAgICAgICAgbWF4VmFsdWU6IE1BWF9NQVhfSU5MSU5FX1NURVBTLFxuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBNQVhfTUFYX0lOTElORV9TVEVQUztcbiAgfVxuICByZXR1cm4gcGFyc2VkO1xufVxuXG4vKipcbiAqIFVwcGVyIGJvdW5kIG9uIHRoZSBzZXJpYWxpemVkIHN0ZXAgaW5wdXQgdGhhdCByZXNpbGllbnQgc3RlcCBkaXNwYXRjaCB3aWxsXG4gKiBpbmxpbmUgaW50byB0aGUgcXVldWUgbWVzc2FnZSdzIGBzdGVwSW5wdXRgLlxuICpcbiAqIFZlcmNlbCBRdWV1ZXMgaGFzIG5vIGhhcmQgbWVzc2FnZS1zaXplIGNhcCAoYm9kaWVzIGFib3ZlIGl0cyB+MjU2IEtCXG4gKiBpbmxpbmUgdGhyZXNob2xkIHRyYW5zcGFyZW50bHkgc3BpbGwgdG8gUzMtYmFja2VkIHN0b3JhZ2UpLCBzbyB0aGlzIGJvdW5kXG4gKiBpcyBhIGNvc3QvbGF0ZW5jeSBjaG9pY2UsIG5vdCBhIHJlamVjdGlvbiBndWFyZDogdGhlIG1lc3NhZ2UgYWxzbyBjYXJyaWVzXG4gKiB0aGUgcnVuSWQsIHN0ZXBJZCwgc3RlcE5hbWUsIGFuZCB0cmFjZSBjYXJyaWVyIGFsb25nc2lkZSBDQk9SIGZyYW1pbmdcbiAqIG92ZXJoZWFkLCBhbmQgc3RheWluZyB1bmRlciB0aGUgcXVldWUncyBpbmxpbmUgdGhyZXNob2xkIGtlZXBzIHN0ZXBcbiAqIG1lc3NhZ2VzIG9uIGl0cyBmYXN0IGlubGluZSBwYXRoIGluc3RlYWQgb2YgcGF5aW5nIGFuIFMzIHN0b3JlK2ZldGNoXG4gKiBkb3VibGUtaG9wIGZvciBieXRlcyB0aGF0IGFscmVhZHkgbGl2ZSBpbiB0aGUgZXZlbnQgbG9nLiBBYm92ZSB0aGlzIHNpemVcbiAqIHRoZSBkaXNwYXRjaCBmYWxscyBiYWNrIHRvIHRoZSBzZXF1ZW50aWFsIHBhdGggKGBzdGVwX2NyZWF0ZWRgIHdyaXRlLCB0aGVuXG4gKiBhIHBheWxvYWQtbGVzcyBxdWV1ZSBtZXNzYWdlKS4gTWF0Y2hlcyBgTUFYX0lOTElORV9SRVNVTUVfUEFZTE9BRF9CWVRFU2BcbiAqIG9uIHRoZSByZXNpbGllbnQgaG9vayByZXN1bWUgcGF0aC5cbiAqL1xuZXhwb3J0IGNvbnN0IE1BWF9SRVNJTElFTlRfU1RFUF9JTlBVVF9CWVRFUyA9IDEyOCAqIDEwMjQ7XG5cbi8qKlxuICogV2hldGhlciByZXNpbGllbnQgc3RlcCBkaXNwYXRjaCBpcyBlbmFibGVkOiB0aGUgc3VzcGVuc2lvbiBoYW5kbGVyXG4gKiBwYXJhbGxlbGl6ZXMgZWFjaCBuZXdseSBjcmVhdGVkIHN0ZXAncyBgc3RlcF9jcmVhdGVkYCBldmVudCB3cml0ZSB3aXRoIGl0c1xuICogc3RlcC1leGVjdXRpb24gcXVldWUgcHVibGlzaCwgY2FycnlpbmcgdGhlIHNlcmlhbGl6ZWQgc3RlcCBpbnB1dCBpbiB0aGVcbiAqIHF1ZXVlIG1lc3NhZ2UgKGBzdGVwSW5wdXRgKSBzbyB0aGUgY29uc3VtZXIgY2FuIGlkZW1wb3RlbnRseSByZS1lbnN1cmUgdGhlXG4gKiBldmVudCBpZiB0aGUgZGlyZWN0IHdyaXRlIGZhaWxlZCB0cmFuc2llbnRseS4gTWlycm9ycyB0aGUgcmVzaWxpZW50IHN0YXJ0XG4gKiAoYHJ1bklucHV0YCkgYW5kIHJlc2lsaWVudCBob29rIHJlc3VtZSAoYGhvb2tJbnB1dGApIHBhdHRlcm5zLlxuICpcbiAqICoqT2ZmIGJ5IGRlZmF1bHQuKiogRW5hYmxlIHZpYSBgV09SS0ZMT1dfUkVTSUxJRU5UX1NURVBfRElTUEFUQ0g9MWAuXG4gKlxuICogVGhlIHF1ZXVlIHB1Ymxpc2ggcmFjZXMgdGhlIGNyZWF0ZSdzIHZlcmRpY3QsIGFuZCBhIGNyZWF0ZSBjYW4gY29tZSBiYWNrXG4gKiByZWZ1c2VkOiBhcyBhIGR1cGxpY2F0ZSB0aGlzIHJlcGxheSBzaG91bGQgc3RvcCBwdXJzdWluZywgb3IgYXMgYSBzdGFsZVxuICogd3JpdGUgb24gYSBXb3JsZCB0aGF0IHJlZnVzZXMgcmF0aGVyIHRoYW4gcmVwb3J0cy4gRWl0aGVyIHdheSB0aGUgbWVzc2FnZVxuICogY2FycnlpbmcgdGhlIHBheWxvYWQgaXMgYWxyZWFkeSBvdXQsIHNvIHRoZSBjb25zdW1lciBjYW4gbWF0ZXJpYWxpemUgYSBzdGVwXG4gKiB3aG9zZSBjcmVhdGUgd2FzIHJlZnVzZWQsIGFuZCBub3RoaW5nIG9yZGVycyB0aGUgdmVyZGljdCBiZWZvcmUgdGhlXG4gKiBjb25zdW1lcidzIHJlZGVsaXZlcnkgcmUtZW5zdXJlLiBFbmFibGluZyB0aGlzIHRyYWRlcyB0aGF0IHdpbmRvdyBmb3IgdGhlXG4gKiBsYXRlbmN5IHRoZSBwYXJhbGxlbCBwdWJsaXNoIHNhdmVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNSZXNpbGllbnRTdGVwRGlzcGF0Y2hFbmFibGVkKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gcHJvY2Vzcy5lbnYuV09SS0ZMT1dfUkVTSUxJRU5UX1NURVBfRElTUEFUQ0ggPT09ICcxJztcbn1cblxuLyoqXG4gKiBXaGV0aGVyIGJhdGNoZWQgZXZlbnQgdHJhbnNpdGlvbnMgYXJlIGVuYWJsZWQ6IHRoZSBzdXNwZW5zaW9uIGhhbmRsZXIgZm9sZHNcbiAqIGEgY2xlYW4gZmFuLW91dCdzIGBzdGVwX2NyZWF0ZWRgICsgYHdhaXRfY3JlYXRlZGAgd3JpdGVzIGludG8gb25lXG4gKiBgd29ybGQuZXZlbnRzLmNyZWF0ZUJhdGNoYCBjYWxsIChvbmUgZHVyYWJsZSB3cml0ZSwgcGVyLWV2ZW50IG91dGNvbWVzKVxuICogaW5zdGVhZCBvZiBvbmUgd3JpdGUgcGVyIGV2ZW50LiBPbmx5IGVuZ2FnZXMgd2hlbiB0aGUgV29ybGQgaW1wbGVtZW50cyB0aGVcbiAqIG9wdGlvbmFsIGBldmVudHMuY3JlYXRlQmF0Y2hgIEFORCB0aGUgcnVuIGlzIG9uIHNsb3QgaWRlbnRpdHlcbiAqIChzcGVjVmVyc2lvbiA+PSA2KSBBTkQgdGhlIHN1c3BlbnNpb24gY2FycmllcyBubyBhdHRyaWJ1dGUvaG9vayB3cml0ZXMgYW5kXG4gKiBubyByZXNpbGllbnQgc3RlcCBkaXNwYXRjaC4gRXZlcnl0aGluZyBlbHNlIGtlZXBzIHRoZSBzaW5nbGUtZXZlbnQgcGF0aFxuICogYnl0ZS1mb3ItYnl0ZS5cbiAqXG4gKiBSZWFkcyBgcHJvY2Vzcy5lbnYuV09SS0ZMT1dfQkFUQ0hfVFJBTlNJVElPTlNgIGxhemlseS4gRGVmYXVsdCAqKk9OKio7XG4gKiBkaXNhYmxlZCBvbmx5IGJ5IGFuIGV4cGxpY2l0IGAnMCdgIC8gYCdmYWxzZSdgIChjYXNlLWluc2Vuc2l0aXZlKSwgdGhlXG4gKiBvcGVyYXRvciBlc2NhcGUgaGF0Y2ggdGhhdCByZXN0b3JlcyB0aGUgZXhhY3QgcHJpb3Igb25lLXdyaXRlLXBlci1ldmVudFxuICogcGF0aCwgbWlycm9yaW5nIGBXT1JLRkxPV19UVVJCT2AncyBraWxsLXN3aXRjaCBzaGFwZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzQmF0Y2hUcmFuc2l0aW9uc0VuYWJsZWQoKTogYm9vbGVhbiB7XG4gIGNvbnN0IHJhdyA9IHByb2Nlc3MuZW52LldPUktGTE9XX0JBVENIX1RSQU5TSVRJT05TO1xuICBpZiAocmF3ID09PSB1bmRlZmluZWQgfHwgcmF3ID09PSAnJykgcmV0dXJuIHRydWU7XG4gIHJldHVybiAhKHJhdyA9PT0gJzAnIHx8IHJhdy50b0xvd2VyQ2FzZSgpID09PSAnZmFsc2UnKTtcbn1cblxuLyoqXG4gKiBDZWlsaW5nIG9uIGV2ZW50cyBwZXIgYGNyZWF0ZUJhdGNoYCBjYWxsIGZyb20gdGhlIGJhdGNoZWQgZmFuLW91dCBmb2xkLlxuICogTWlycm9ycyB0aGUgc2VydmVyJ3MgdHJhbnNhY3Rpb24gYnVkZ2V0cyB3aXRoIGEgY29tZm9ydGFibGUgbWFyZ2luOiBlYWNoXG4gKiBmYW4tb3V0IGV2ZW50IGNvc3RzIDIgdHJhbnNhY3Rpb24gaXRlbXMgc2VydmVyLXNpZGUgKGVudGl0eSArIGV2ZW50IHJvdylcbiAqIGFnYWluc3QgdGhlIDEwMC1pdGVtIER5bmFtb0RCIGNhcCwgYW5kIGlubGluZSBwYXlsb2FkcyBjb3VudCBhZ2FpbnN0IGFcbiAqIDc2OCBLQiBieXRlIGJ1ZGdldCwgc28gMzIgZXZlbnRzIHN0YXlzIHdlbGwgdW5kZXIgYm90aCwgYW5kIGEgZmFuLW91dCBsYXJnZXJcbiAqIHRoYW4gdGhpcyBjb21taXRzIGluIHN1Y2Nlc3NpdmUgYmF0Y2hlcyAoc3BsaXQgYmF0Y2hlcyBsb3NlXG4gKiBjcm9zcy1iYXRjaCBhdG9taWNpdHksIHdoaWNoIGlzIGV4YWN0bHkgdG9kYXkncyBwZXItZXZlbnQtd3JpdGUgY3Jhc2hcbiAqIHN1cmZhY2UsIGFuZCBldmVyeSBiYXRjaCBzdGlsbCBjb252ZXJnZXMgb24gcmV0cnkgdmlhIHBlci1ldmVudCA0MDlzKS5cbiAqL1xuZXhwb3J0IGNvbnN0IE1BWF9CQVRDSF9GQU5PVVRfRVZFTlRTID0gMzI7XG5cbi8qKlxuICogT3B0aW9uYWwgY2xpZW50LXNpZGUgb3ZlcnJpZGUgZm9yIHRoZSBzZXJ2ZXItc3VwcGxpZWQgcGVyLXJ1biBldmVudCBjZWlsaW5nLlxuICogV2hlbiBzZXQgdG8gYSBwb3NpdGl2ZSBpbnRlZ2VyLCB0aGUgcnVudGltZSBjbGFtcHMgdGhlIHNlcnZlcidzIGxpbWl0ICpkb3duKlxuICogdG8gdGhpcyB2YWx1ZSAobmV2ZXIgcmFpc2VzIGl0KSBzbyBlbmZvcmNlbWVudCBjYW4gYmUgZXhlcmNpc2VkIHdpdGhvdXQgYVxuICogc2VydmVyLXNpZGUgY2hhbmdlLiBgdW5kZWZpbmVkYCAodW5zZXQpIOKHkiB1c2UgdGhlIHNlcnZlciB2YWx1ZSBhcy1pcy5cbiAqXG4gKiBSZWFkcyBgcHJvY2Vzcy5lbnYuV09SS0ZMT1dfTUFYX0VWRU5UU19PVkVSUklERWAgbGF6aWx5IHNvIHRlc3RzIGFuZFxuICogZGVwbG95bWVudHMgY2FuIG92ZXJyaWRlIHBlciBpbnZvY2F0aW9uLiBJbnZhbGlkIHZhbHVlcyBmYWxsIGJhY2sgdG8gdW5zZXRcbiAqIChubyB0aHJvdzogdGhlIGVudiB2YXIgaXMgYW4gZXNjYXBlIGhhdGNoKSBhbmQgZW1pdCBhIG9uZS10aW1lIHdhcm5pbmcuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRNYXhFdmVudHNPdmVycmlkZSgpOiBudW1iZXIgfCB1bmRlZmluZWQge1xuICBjb25zdCByYXcgPSBwcm9jZXNzLmVudi5XT1JLRkxPV19NQVhfRVZFTlRTX09WRVJSSURFO1xuICBpZiAoIXJhdykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgY29uc3QgcGFyc2VkID0gTnVtYmVyKHJhdyk7XG4gIGlmICghTnVtYmVyLmlzSW50ZWdlcihwYXJzZWQpIHx8IHBhcnNlZCA8PSAwKSB7XG4gICAgaWYgKCF3YXJuZWQubWF4RXZlbnRzVmFsdWVzLmhhcyhyYXcpKSB7XG4gICAgICB3YXJuZWQubWF4RXZlbnRzVmFsdWVzLmFkZChyYXcpO1xuICAgICAgcnVudGltZUxvZ2dlci53YXJuKFxuICAgICAgICAnSWdub3JpbmcgV09SS0ZMT1dfTUFYX0VWRU5UU19PVkVSUklERTogbm90IGEgcG9zaXRpdmUgaW50ZWdlcjsgdXNpbmcgc2VydmVyIGxpbWl0JyxcbiAgICAgICAgeyByYXcgfVxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuICByZXR1cm4gcGFyc2VkO1xufVxuXG4vKipcbiAqIFdoZXRoZXIgb3B0aW1pc3RpYyBpbmxpbmUgc3RlcCBzdGFydCBpcyBlbmFibGVkLiBXaGVuIG9uLCB0aGUgb3duZWQtaW5saW5lXG4gKiBwYXRoIGJlZ2lucyBydW5uaW5nIGEgYnJhbmQtbmV3IHN0ZXAncyBib2R5ICpiZWZvcmUqIGl0cyBsYXp5IGBzdGVwX3N0YXJ0ZWRgXG4gKiBuZXR3b3JrIGNhbGwgcmVzb2x2ZXMgKHRoZSBpbnB1dCBpcyBhbHJlYWR5IGtub3duIGxvY2FsbHkpLCBhd2FpdGluZyB0aGVcbiAqIGBzdGVwX3N0YXJ0ZWRgIG9ubHkgYmVmb3JlIHRoZSB0ZXJtaW5hbCB3cml0ZS5cbiAqXG4gKiBUaGlzIGNhbiBydW4gYSBzdGVwIGJvZHkgbW9yZSB0aGFuIG9uY2Ugd2hlbiBoYW5kbGVycyByYWNlIGZvciB0aGUgc2FtZVxuICogc3RlcCdzIGNyZWF0ZS1jbGFpbTogYm90aCBydW4gdGhlIGJvZHkgYmVmb3JlIG9uZSB3aW5zLiBUaGF0IGlzIHVuc2FmZSBmb3JcbiAqIHN0ZXBzIHdpdGggbm9uLWlkZW1wb3RlbnQgc2lkZSBlZmZlY3RzOyBpbiBwYXJ0aWN1bGFyLCB0d28gY29uY3VycmVudCBydW5zXG4gKiBvZiBhIHN0ZXAgdGhhdCB3cml0ZXMgdG8gdGhlIHdvcmtmbG93IHN0cmVhbSAoZS5nLiBhbiBBSSBhZ2VudCBzdHJlYW1pbmdcbiAqIHRva2VucykgY2FuIGludGVybGVhdmUgYW5kIGNvcnJ1cHQgdGhlIHN0cmVhbSBkYXRhLiBTbyB0aGUgb3B0aW1pemF0aW9uIGlzXG4gKiAqKm9mZiBieSBkZWZhdWx0KiogYW5kIG11c3QgYmUgZXhwbGljaXRseSBvcHRlZCBpbnRvIHBlciBkZXBsb3ltZW50LlxuICpcbiAqIFJlYWRzIGBwcm9jZXNzLmVudi5XT1JLRkxPV19PUFRJTUlTVElDX0lOTElORV9TVEFSVGAgbGF6aWx5LiBEZWZhdWx0IE9GRjtcbiAqIGVuYWJsZWQgb25seSBieSBhbiBleHBsaWNpdCBgJzEnYCAvIGAndHJ1ZSdgLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNPcHRpbWlzdGljSW5saW5lU3RhcnRFbmFibGVkKCk6IGJvb2xlYW4ge1xuICBjb25zdCByYXcgPSBwcm9jZXNzLmVudi5XT1JLRkxPV19PUFRJTUlTVElDX0lOTElORV9TVEFSVDtcbiAgaWYgKHJhdyA9PT0gdW5kZWZpbmVkIHx8IHJhdyA9PT0gJycpIHJldHVybiBmYWxzZTtcbiAgcmV0dXJuIHJhdyA9PT0gJzEnIHx8IHJhdy50b0xvd2VyQ2FzZSgpID09PSAndHJ1ZSc7XG59XG5cbi8qKlxuICogV2hldGhlciBhbiBvcGVyYXRvciBoYXMgKipleHBsaWNpdGx5IGRpc2FibGVkKiogb3B0aW1pc3RpYyBpbmxpbmUgc3RhcnQgdmlhXG4gKiBgV09SS0ZMT1dfT1BUSU1JU1RJQ19JTkxJTkVfU1RBUlQ9MGAgLyBgPWZhbHNlYC4gRGlzdGluY3QgZnJvbSBcInVuc2V0XCI6IHVuc2V0XG4gKiBsZWF2ZXMgdGhlIG9wdGltaXphdGlvbiBvZmYgYnkgZGVmYXVsdCBidXQgbGV0cyB0dXJibyBmb3JjZSBpdCBvbjsgYW4gZXhwbGljaXRcbiAqIGAwYC9gZmFsc2VgIGlzIGFuIG9wZXJhdG9yIG9wdC1vdXQgdGhhdCB0dXJibyBtdXN0IGhvbm9yICh0dXJibydzIGZvcmNlZFxuICogb3B0aW1pc3RpYyBzdGFydCBzdGlsbCBydW5zIGEgc3RlcCBib2R5IGJlZm9yZSBgc3RlcF9zdGFydGVkYC9gcnVuX3N0YXJ0ZWRgIGlzXG4gKiBjb25maXJtZWQsIHRoZSBwcm9wZXJ0eSBzdWNoIGFuIG9wZXJhdG9yIGlzIG9wdGluZyBvdXQgb2YpLCBzb1xuICogYGZvcmNlT3B0aW1pc3RpY1N0YXJ0YCBkZWZlcnMgdG8gdGhpcy4gUmVhZHMgdGhlIGVudiB2YXIgbGF6aWx5LlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNPcHRpbWlzdGljSW5saW5lU3RhcnRFeHBsaWNpdGx5RGlzYWJsZWQoKTogYm9vbGVhbiB7XG4gIGNvbnN0IHJhdyA9IHByb2Nlc3MuZW52LldPUktGTE9XX09QVElNSVNUSUNfSU5MSU5FX1NUQVJUO1xuICBpZiAocmF3ID09PSB1bmRlZmluZWQgfHwgcmF3ID09PSAnJykgcmV0dXJuIGZhbHNlO1xuICByZXR1cm4gcmF3ID09PSAnMCcgfHwgcmF3LnRvTG93ZXJDYXNlKCkgPT09ICdmYWxzZSc7XG59XG5cbi8qKlxuICogV2hldGhlciBcInR1cmJvIG1vZGVcIiBpcyBlbmFibGVkLiBUdXJibyBtb2RlIGZhc3QtcGF0aHMgdGhlICpmaXJzdCBkZWxpdmVyeSBvZlxuICogdGhlIGZpcnN0IGludm9jYXRpb24qIG9mIGEgcnVuIChkZXRlY3RlZCBieSB0aGUgZW50cnlwb2ludCB2aWEgYHJ1bklucHV0YFxuICogcHJlc2VuY2UgKyBgbWV0YWRhdGEuYXR0ZW1wdCA9PT0gMWApOiBpdCBiYWNrZ3JvdW5kcyB0aGUgYHJ1bl9zdGFydGVkYCBldmVudFxuICogY3JlYXRpb24sIHNraXBzIHRoZSBpbml0aWFsIGV2ZW50LWxvZyBsb2FkIChub3RoaW5nIGhhcyBiZWVuIHdyaXR0ZW4geWV0KSxcbiAqIGFuZCBmb3JjZXMgb3B0aW1pc3RpYyBpbmxpbmUgc3RlcCBzdGFydCBmb3IgdGhhdCBpbnZvY2F0aW9uLCBpbmRlcGVuZGVudCBvZlxuICogYFdPUktGTE9XX09QVElNSVNUSUNfSU5MSU5FX1NUQVJUYC5cbiAqXG4gKiBGb3JjaW5nIG9wdGltaXN0aWMgc3RhcnQgaXMgc2FmZSBoZXJlIGJlY2F1c2UgdGhlIGZpcnN0IGRlbGl2ZXJ5IGhhcyBub1xuICogY29uY3VycmVudCBwZWVyIGhhbmRsZXIgdG8gcmFjZSB0aGUgc3RlcCBjcmVhdGUtY2xhaW0sIHNvIGEgc3RlcCBib2R5IHJ1bnNcbiAqIGV4YWN0bHkgb25jZS4gVGhhdCBzaW5nbGUtaGFuZGxlciBndWFyYW50ZWUgZW5kcyBhcyBzb29uIGFzIHRoZSBydW4gY3JlYXRlcyBhXG4gKiBob29rIG9yIHdhaXQgKHdoaWNoIGludHJvZHVjZSByZXN1bWUvcGFyYWxsZWwgaW52b2NhdGlvbnMpLCBzbyB0aGUgcnVudGltZVxuICogZXhpdHMgdHVyYm8gYXQgdGhhdCBwb2ludC5cbiAqXG4gKiBSZWFkcyBgcHJvY2Vzcy5lbnYuV09SS0ZMT1dfVFVSQk9gIGxhemlseS4gRGVmYXVsdCAqKk9OKio7IGRpc2FibGVkIG9ubHkgYnkgYW5cbiAqIGV4cGxpY2l0IGAnMCdgIC8gYCdmYWxzZSdgIChjYXNlLWluc2Vuc2l0aXZlKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVHVyYm9FbmFibGVkKCk6IGJvb2xlYW4ge1xuICBjb25zdCByYXcgPSBwcm9jZXNzLmVudi5XT1JLRkxPV19UVVJCTztcbiAgaWYgKHJhdyA9PT0gdW5kZWZpbmVkIHx8IHJhdyA9PT0gJycpIHJldHVybiB0cnVlO1xuICByZXR1cm4gIShyYXcgPT09ICcwJyB8fCByYXcudG9Mb3dlckNhc2UoKSA9PT0gJ2ZhbHNlJyk7XG59XG5cbi8qKlxuICogV2hldGhlciB0aGUgUXVpY2tKUyBlbmdpbmUncyBiYXNlbGluZS1zbmFwc2hvdCBzdGFydHVwIG9wdGltaXphdGlvbiBpc1xuICogZW5hYmxlZCAoZGVmYXVsdCBPTikuIFdoZW4gb24sIHRoZSBlbmdpbmUgaHlkcmF0ZXMgYSBWTSB3aXRoIHRoZVxuICogd29ya2Zsb3cgYnVuZGxlIG9uY2UgcGVyIGZ1bmN0aW9uIGluc3RhbmNlLCBzbmFwc2hvdHMgaXQsIGFuZCBzdGFydHNcbiAqIGV2ZXJ5IGludm9jYXRpb24gYnkgcmVzdG9yaW5nIHRoZSBzbmFwc2hvdCBpbnN0ZWFkIG9mIHJlLWV2YWx1YXRpbmdcbiAqIHRoZSBidW5kbGUsIHNraXBwaW5nIHRoZSBkb21pbmFudCBzaGFyZSBvZiBWTSBzdGFydHVwIChtZWFzdXJlZFxuICogfjc3bXMg4oaSIH4zbXMgdG8gZmlyc3Qgc3VzcGVuc2lvbiBmb3IgYSAxLjNNQiBidW5kbGUpLiBCdW5kbGVzIHdob3NlXG4gKiBtb2R1bGUgc2NvcGUgY29uc3VtZXMgcmFuZG9tbmVzcywgcmVhZHMgdGhlIGNsb2NrLCBvciByZXBsYWNlcyBhXG4gKiBzZXJpYWxpemF0aW9uIGludHJpbnNpYyBhcmUgZGV0ZWN0ZWQgYXQgaHlkcmF0ZSB0aW1lIGFuZFxuICogYXV0b21hdGljYWxseSBmYWxsIGJhY2sgdG8gcGVyLWludm9jYXRpb24gZnJlc2ggZXZhbHVhdGlvbiAoc2VlXG4gKiBwcmVwYXJlQmFzZWxpbmVTbmFwc2hvdCkuIFNldCBXT1JLRkxPV19RVUlDS0pTX0JBU0VMSU5FX1NOQVBTSE9UPTAgdG9cbiAqIGRpc2FibGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1F1aWNrSlNCYXNlbGluZVNuYXBzaG90RW5hYmxlZCgpOiBib29sZWFuIHtcbiAgY29uc3QgcmF3ID0gcHJvY2Vzcy5lbnYuV09SS0ZMT1dfUVVJQ0tKU19CQVNFTElORV9TTkFQU0hPVDtcbiAgaWYgKHJhdyA9PT0gdW5kZWZpbmVkIHx8IHJhdyA9PT0gJycpIHJldHVybiB0cnVlO1xuICByZXR1cm4gIShyYXcgPT09ICcwJyB8fCByYXcudG9Mb3dlckNhc2UoKSA9PT0gJ2ZhbHNlJyk7XG59XG5cbi8qKlxuICogV2hldGhlciB0aGUgaW5saW5lIGxvb3AgcmV0YWlucyBhIHN1c3BlbmRlZCB3b3JrZmxvdyBWTSBhY3Jvc3MgaW5saW5lIHN0ZXBzXG4gKiB3aXRoaW4gb25lIGludm9jYXRpb24gKGRlZmF1bHQgT04pLiBXaGVuIG9uLCBhIHN0ZXAtb25seSBzdXNwZW5zaW9uIGtlZXBzXG4gKiB0aGUgbGl2ZSBWTSwgZXZlbnQgY29uc3VtZXIsIGFuZCBoeWRyYXRlZCBzdGF0ZSBhbGl2ZSwgYW5kIHRoZSBuZXh0IGxvb3BcbiAqIGl0ZXJhdGlvbiBhcHBlbmRzIG9ubHkgdGhlIG5ld2x5IGR1cmFibGUgZXZlbnRzIGluc3RlYWQgb2YgcmVidWlsZGluZyB0aGVcbiAqIGB2bS5Db250ZXh0YCBhbmQgcmVwbGF5aW5nIHRoZSB3aG9sZSBldmVudCBsb2cuIE5vbi1zdGVwIHN1c3BlbnNpb25zIGFuZFxuICogcmVwbGF5IGRpdmVyZ2VuY2UgYWx3YXlzIGZhbGwgYmFjayB0byB0aGUgb3JkaW5hcnkgZHVyYWJsZSByZXBsYXkgcGF0aC5cbiAqXG4gKiBgV09SS0ZMT1dfUkVUQUlORURfVk09MGAgKG9yIGBmYWxzZWApIGlzIHRoZSBraWxsIHN3aXRjaDogZXZlcnkgaXRlcmF0aW9uXG4gKiByZXBsYXlzIGZyb20gc2NyYXRjaCBpbiBhIGZyZXNoIFZNLCBtYXRjaGluZyB0aGUgcHJlLXJldGVudGlvbiBiZWhhdmlvci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVm1SZXRlbnRpb25FbmFibGVkKCk6IGJvb2xlYW4ge1xuICBjb25zdCByYXcgPSBwcm9jZXNzLmVudi5XT1JLRkxPV19SRVRBSU5FRF9WTTtcbiAgaWYgKHJhdyA9PT0gdW5kZWZpbmVkIHx8IHJhdyA9PT0gJycpIHJldHVybiB0cnVlO1xuICByZXR1cm4gIShyYXcgPT09ICcwJyB8fCByYXcudG9Mb3dlckNhc2UoKSA9PT0gJ2ZhbHNlJyk7XG59XG5cbi8qKlxuICogV2hldGhlciBpbmxpbmUgc3RlcCBvd25lcnNoaXAgaXMgZW5hYmxlZCAoZGVmYXVsdCBPTikuIFdoZW4gb24sIHRoZSBsYXp5XG4gKiBgc3RlcF9zdGFydGVkYCB0aGF0IGNyZWF0ZXMgYW4gaW5saW5lIHN0ZXAgcmVjb3JkcyB0aGUgb3duaW5nIHF1ZXVlXG4gKiBtZXNzYWdlIElELCBhbmQgd2FrZSByZXBsYXlzIHRoYXQgb2JzZXJ2ZSBhbiBhY3RpdmVseS1vd25lZCBzdGVwIGVucXVldWUgYVxuICogKmRlbGF5ZWQgYmFja3N0b3AqIG1lc3NhZ2UgaW5zdGVhZCBvZiBpbW1lZGlhdGVseSByZXF1ZXVlaW5nIGl0LCBmaXhpbmdcbiAqIGR1cGxpY2F0ZSBpbmxpbmUgc3RlcCBleGVjdXRpb24gd2hlbiBhIGhvb2svd2FpdCB3YWtlcyBhIHJ1biBtaWQtc3RlcFxuICogKHZlcmNlbC93b3JrZmxvdyMyNzgwKS5cbiAqXG4gKiBgV09SS0ZMT1dfSU5MSU5FX09XTkVSU0hJUD0wYCAob3IgYGZhbHNlYCkgaXMgdGhlIGtpbGwgc3dpdGNoOiBkaXNwYXRjaFxuICogcmV2ZXJ0cyB0byB0aGUgdW5jb25kaXRpb25hbCBpbW1lZGlhdGUgcmVxdWV1ZS4gU3RhbXBpbmcgaXMgdW5hZmZlY3RlZDpcbiAqIHRoZSByZWNvcmRlZCBvd25lck1lc3NhZ2VJZCBpcyBpbmVydCBkYXRhIHdoZW4gdGhlIHN3aXRjaCBpcyBvZmYuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0lubGluZU93bmVyc2hpcEVuYWJsZWQoKTogYm9vbGVhbiB7XG4gIGNvbnN0IHJhdyA9IHByb2Nlc3MuZW52LldPUktGTE9XX0lOTElORV9PV05FUlNISVA7XG4gIGlmIChyYXcgPT09IHVuZGVmaW5lZCB8fCByYXcgPT09ICcnKSByZXR1cm4gdHJ1ZTtcbiAgcmV0dXJuICEocmF3ID09PSAnMCcgfHwgcmF3LnRvTG93ZXJDYXNlKCkgPT09ICdmYWxzZScpO1xufVxuXG4vKipcbiAqIERlZmF1bHQgaW5saW5lLW93bmVyc2hpcCBsZWFzZSwgaW4gc2Vjb25kczogaG93IGxvbmcgYWZ0ZXIgYSBzdGVwJ3MgbGF0ZXN0XG4gKiAoc3RhbXBlZCkgYHN0ZXBfc3RhcnRlZGAgYSBub24tb3duZXIgaW52b2NhdGlvbiBhc3N1bWVzIHRoZSBvd25pbmdcbiAqIGludm9jYXRpb24gbWF5IHN0aWxsIGJlIGFsaXZlLiBXaXRoaW4gdGhlIGxlYXNlLCB3YWtlIHJlcGxheXMgZW5xdWV1ZSB0aGVcbiAqIHN0ZXAncyBiYWNrc3RvcCBtZXNzYWdlIHdpdGggYGRlbGF5U2Vjb25kcyA9IGxlYXNlIHJlbWFpbmluZ2AgaW5zdGVhZCBvZlxuICogaW1tZWRpYXRlbHk7IHBhc3QgaXQsIHRoZXkgZW5xdWV1ZSBpbW1lZGlhdGVseSAodG9kYXkncyBiZWhhdmlvcikuXG4gKlxuICogV2h5IGEgZml4ZWQgODYwIGFuZCBub3QgYSB2YWx1ZSBkZXJpdmVkIGZyb20gdGhlIGZ1bmN0aW9uJ3MgYG1heER1cmF0aW9uYDpcbiAqIG5laXRoZXIgcnVudGltZSBub3IgYnVpbGQgdGltZSBjYW4gc2VlIHRoZSByZXNvbHZlZCB2YWx1ZTogYnVpbGRlcnMgZW1pdFxuICogYG1heER1cmF0aW9uOiAnbWF4J2AsIHdoaWNoIHRoZSBwbGF0Zm9ybSByZXNvbHZlcyBwZXItcGxhbiBhdCBkZXBsb3ksIGFuZFxuICogbm8gZW52IHZhciBvciByZXF1ZXN0LWNvbnRleHQgZGVhZGxpbmUgQVBJIGV4cG9zZXMgdGhlIHJlc3VsdC4gVGhlIGJvdW5kXG4gKiBjb21lcyBmcm9tIGEgcGxhdGZvcm0gcnVsZSBpbnN0ZWFkOiBkdXJhdGlvbnMgYWJvdmUgODAwcyByZXF1aXJlIGV4cGxpY2l0XG4gKiBwZXItZnVuY3Rpb24gbnVtZXJpYyBjb25maWcsIHNvIGEgYnVpbGRlci1lbWl0dGVkIGAnbWF4J2AgcmVzb2x2ZXMgdG8gYXRcbiAqIG1vc3QgODAwcywgYW5kIDg2MHMgdGhlcmVmb3JlIGRvbWluYXRlcyBhbnkgd29ya2Zsb3cgcm91dGUncyBpbnZvY2F0aW9uXG4gKiBsaWZldGltZSBwbHVzIHNjaGVkdWxpbmcgc2xhY2suIFJldmlzaXQgd2hlbiB0aGF0IGNlaWxpbmcgbW92ZXMgKHRoZVxuICogMzAtbWludXRlIGR1cmF0aW9uIGJldGEgYmVjb21pbmcgcmVhY2hhYmxlIHZpYSBgJ21heCdgIHdvdWxkIGludmFsaWRhdGVcbiAqIHRoZSBib3VuZCkuIFdvcmxkcyB3aXRob3V0IGFuIGludm9jYXRpb24ga2lsbCBib3VuZCAod29ybGQtbG9jYWwsXG4gKiBzZWxmLWhvc3RlZCkgZ2V0IG5vIGRlYXRoIHByb29mIGZyb20gYW55IGNvbnN0YW50LiBUaGVyZSB0aGUgaW4tcHJvY2Vzc1xuICogc2luZ2xlLWZsaWdodCBsYXllciAoc3RlcC1zaW5nbGUtZmxpZ2h0LnRzKSBpcyB3aGF0IG1ha2VzIGEgYmFja3N0b3BcbiAqIGZpcmluZyBtaWQtc3RlcCBoYXJtbGVzcy5cbiAqXG4gKiA4NjAgYWxzbyBzdGF5cyB1bmRlciB0aGUgcXVldWUncyA5MDBzIG1heGltdW0gZGVsYXkgKFNRUyBjYXApLCBzbyBhXG4gKiBiYWNrc3RvcCdzIGZ1bGwgbGVhc2UgcmVtYWluZGVyIGFsd2F5cyBmaXRzIGluIGEgc2luZ2xlIGRlbGF5ZWQgbWVzc2FnZS5cbiAqXG4gKiBPdmVycmlkZSB2aWEgYFdPUktGTE9XX0lOTElORV9PV05FUlNISVBfTEVBU0VfU0VDT05EU2AgKGNsYW1wZWQgdG9cbiAqIDEuLmBNQVhfSU5MSU5FX09XTkVSU0hJUF9MRUFTRV9TRUNPTkRTYCkuXG4gKi9cbmV4cG9ydCBjb25zdCBJTkxJTkVfT1dORVJTSElQX0xFQVNFX1NFQ09ORFMgPSA4NjA7XG5cbi8qKlxuICogVXBwZXIgYm91bmQgZm9yIHRoZSBsZWFzZSBlbnYgb3ZlcnJpZGUuIDkwMHMgaXMgdGhlIHF1ZXVlJ3MgbWF4aW11bVxuICogcGVyLW1lc3NhZ2UgZGVsYXkgKFNRUyBjYXApLiBBIGxvbmdlciBsZWFzZSB3b3VsZCBuZWVkIGRlbGF5IGNoYWluaW5nXG4gKiBsaWtlIGxvbmcgd2FpdHMgdXNlOyBjbGFtcCBpbnN0ZWFkIHNvIG9uZSBkZWxheWVkIG1lc3NhZ2UgYWx3YXlzIHN1ZmZpY2VzLlxuICovXG5leHBvcnQgY29uc3QgTUFYX0lOTElORV9PV05FUlNISVBfTEVBU0VfU0VDT05EUyA9IDkwMDtcblxuLyoqXG4gKiBFZmZlY3RpdmUgaW5saW5lLW93bmVyc2hpcCBsZWFzZS4gT3ZlcnJpZGUgdmlhXG4gKiBgV09SS0ZMT1dfSU5MSU5FX09XTkVSU0hJUF9MRUFTRV9TRUNPTkRTYCwgZS5nLiByYWlzZSBpdCBvbiBzZWxmLWhvc3RlZFxuICogbXVsdGktaW5zdGFuY2Ugd29ybGRzIHdpdGggbG9uZy1ydW5uaW5nIHN0ZXBzIHRvIHdpZGVuIHRoZSB3aW5kb3cgaW4gd2hpY2hcbiAqIGEgbGl2ZSBvd25lciBpcyBwcm90ZWN0ZWQgZnJvbSBhIGNvbmN1cnJlbnQgYmFja3N0b3AgZXhlY3V0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0SW5saW5lT3duZXJzaGlwTGVhc2VTZWNvbmRzKCk6IG51bWJlciB7XG4gIHJldHVybiBlbnZOdW1iZXIoXG4gICAgJ1dPUktGTE9XX0lOTElORV9PV05FUlNISVBfTEVBU0VfU0VDT05EUycsXG4gICAgSU5MSU5FX09XTkVSU0hJUF9MRUFTRV9TRUNPTkRTLFxuICAgIHsgaW50ZWdlcjogdHJ1ZSwgbWluOiAxLCBtYXg6IE1BWF9JTkxJTkVfT1dORVJTSElQX0xFQVNFX1NFQ09ORFMgfVxuICApO1xufVxuXG4vLyBBIHJlcGxheS1jb25zdW1lciBtaXNtYXRjaCBjYW4gYmUgY2F1c2VkIGJ5IGEgdHJhbnNpZW50IGRpdmVyZ2VudCByZXBsYXlcbi8vIHJhdGhlciB0aGFuIGFuIGludmFsaWQgcGVyc2lzdGVkIGhpc3RvcnkuIFF1ZXVlIGJvdW5kZWQgcmVjb3ZlcnkgcmVwbGF5c1xuLy8gYmVmb3JlIHJlY29yZGluZyB0ZXJtaW5hbCBjb3JydXB0aW9uIGZvciBhIHJ1biB0aGF0IGNhbm5vdCByZXBsYXkuXG5leHBvcnQgY29uc3QgUkVQTEFZX0RJVkVSR0VOQ0VfTUFYX1JFVFJJRVMgPSAzO1xuXG4vKipcbiAqIEVmZmVjdGl2ZSByZXBsYXktZGl2ZXJnZW5jZSByZWNvdmVyeSBidWRnZXQuIE92ZXJyaWRlIHZpYVxuICogYFdPUktGTE9XX1JFUExBWV9ESVZFUkdFTkNFX01BWF9SRVRSSUVTYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFJlcGxheURpdmVyZ2VuY2VNYXhSZXRyaWVzKCk6IG51bWJlciB7XG4gIHJldHVybiBlbnZOdW1iZXIoXG4gICAgJ1dPUktGTE9XX1JFUExBWV9ESVZFUkdFTkNFX01BWF9SRVRSSUVTJyxcbiAgICBSRVBMQVlfRElWRVJHRU5DRV9NQVhfUkVUUklFUyxcbiAgICB7IGludGVnZXI6IHRydWUgfVxuICApO1xufVxuXG4vLyBBIHN0YWxlLXNuYXBzaG90IHJlamVjdGlvbiAoNDEyKSBtZWFucyB0aGUgcmVwbGF5J3MgZXZlbnQgbG9nIHdhcyBtaXNzaW5nIGFuXG4vLyBldmVudCB0aGUgV29ybGQgaGFkIGFscmVhZHkgcmVjb3JkZWQsIHNvIHRoZSByZXBsYXkgaXMgcmUtZGVyaXZlZCBmcm9tIGFcbi8vIGNvcnJlY3RlZCBsb2cgaW5zaWRlIHRoZSBzYW1lIGludm9jYXRpb24uIEJvdW5kZWQgYmVjYXVzZSBhIHBlcnNpc3RlbnRseVxuLy8gcmVqZWN0ZWQgd3JpdGUgc2hvdWxkIGVzY2FsYXRlIHJhdGhlciB0aGFuIHNwaW46IGFmdGVyIHRoaXMgbWFueSByZXN0YXJ0cyB0aGVcbi8vIHJ1biBpcyByZS1pbnZva2VkIChhIG5ldyBpbnZvY2F0aW9uLCBwb3NzaWJseSBpbiBhIGRpZmZlcmVudCByZWdpb24pLCBhbmQgdGhlXG4vLyBydW4tbGV2ZWwgYnVkZ2V0IGJlbG93IHRoZW4gYXBwbGllcy5cbmV4cG9ydCBjb25zdCBQUkVDT05ESVRJT05fTUFYX0lOUFJPQ0VTU19SRVNUQVJUUyA9IDM7XG5cbi8qKlxuICogRWZmZWN0aXZlIGluLXByb2Nlc3MgcmVwbGF5LXJlc3RhcnQgYnVkZ2V0IGZvciBzdGFsZS1zbmFwc2hvdCByZWplY3Rpb25zLlxuICogT3ZlcnJpZGUgdmlhIGBXT1JLRkxPV19QUkVDT05ESVRJT05fTUFYX0lOUFJPQ0VTU19SRVNUQVJUU2AuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRQcmVjb25kaXRpb25NYXhJblByb2Nlc3NSZXN0YXJ0cygpOiBudW1iZXIge1xuICByZXR1cm4gZW52TnVtYmVyKFxuICAgICdXT1JLRkxPV19QUkVDT05ESVRJT05fTUFYX0lOUFJPQ0VTU19SRVNUQVJUUycsXG4gICAgUFJFQ09ORElUSU9OX01BWF9JTlBST0NFU1NfUkVTVEFSVFMsXG4gICAgeyBpbnRlZ2VyOiB0cnVlIH1cbiAgKTtcbn1cblxuLy8gVGhlIGluLXByb2Nlc3MgYnVkZ2V0IGFib3ZlIGlzIHBlci1pbnZvY2F0aW9uLCBhbmQgYSByZS1pbnZvY2F0aW9uIHRoYXRcbi8vIGVucXVldWVzIGEgZnJlc2ggbWVzc2FnZSBhbHNvIHJlc3RhcnRzIHRoZSBxdWV1ZSdzIGRlbGl2ZXJ5IGNvdW50LCBzbyB3aXRob3V0XG4vLyBhIGNvdW50ZXIgY2FycmllZCBvbiB0aGUgbWVzc2FnZSBhIHBlcm1hbmVudGx5IGZlbmNlZCBydW4gaGFzIG5vIHJ1bi1sZXZlbFxuLy8gYm91bmQgYXQgYWxsLiBJdCBjYW4gc3RheSBmZW5jZWQgd2l0aG91dCBhbnkgcGVybWFuZW50IGZhdWx0IChhIGZ1bGwgcmVsb2FkXG4vLyBpcyBub3QgYXRvbWljIGFjcm9zcyBwYWdlcywgc28gYSBidXN5IHJ1biBjYW4gYWNxdWlyZSBhIG5ldyBob2xlIG9uIGV2ZXJ5XG4vLyByZWxvYWQpLCBzbyB0aGUgY2hhaW4gaXMgY291bnRlZCBhbmQgdGhlIHJ1biBmYWlscyBvbmNlIHRoaXMgbWFueVxuLy8gcmUtaW52b2NhdGlvbnMgaGF2ZSBiZWVuIHNwZW50IG9uIHN0YWxlLXNuYXBzaG90IHJlamVjdGlvbnMuXG5leHBvcnQgY29uc3QgUFJFQ09ORElUSU9OX01BWF9SRUlOVk9DQVRJT05TID0gNTtcblxuLyoqXG4gKiBFZmZlY3RpdmUgcGVyLXJ1biBidWRnZXQgZm9yIHJlLWludm9jYXRpb25zIGNhdXNlZCBieSBzdGFsZS1zbmFwc2hvdFxuICogcmVqZWN0aW9ucy4gT3ZlcnJpZGUgdmlhIGBXT1JLRkxPV19QUkVDT05ESVRJT05fTUFYX1JFSU5WT0NBVElPTlNgLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0UHJlY29uZGl0aW9uTWF4UmVpbnZvY2F0aW9ucygpOiBudW1iZXIge1xuICByZXR1cm4gZW52TnVtYmVyKFxuICAgICdXT1JLRkxPV19QUkVDT05ESVRJT05fTUFYX1JFSU5WT0NBVElPTlMnLFxuICAgIFBSRUNPTkRJVElPTl9NQVhfUkVJTlZPQ0FUSU9OUyxcbiAgICB7IGludGVnZXI6IHRydWUgfVxuICApO1xufVxuXG4vLyBCYWNrb2ZmIGJlZm9yZSBhIHByZWNvbmRpdGlvbiByZS1pbnZvY2F0aW9uLiBVbmxpa2UgdGhlIGluLXByb2Nlc3MgcmVzdGFydFxuLy8gKHdoZXJlIHRoZSBwb2ludCBpcyB0byByZS1yZWFkIGltbWVkaWF0ZWx5KSwgYSByZS1pbnZvY2F0aW9uIG9ubHkgaGFwcGVuc1xuLy8gYWZ0ZXIgdGhlIGluLXByb2Nlc3MgYnVkZ2V0IGZhaWxlZCB0byBjYXRjaCB1cCwgc28gdGhlIGxvZyBpcyBiZWluZyBleHRlbmRlZFxuLy8gZmFzdGVyIHRoYW4gdGhpcyByZXBsYXkgY2FuIGZvbGxvdyBpdC4gV2FpdGluZyBsZXRzIHRoZSB3cml0ZXJzIHF1aWVzY2UuXG5leHBvcnQgY29uc3QgUFJFQ09ORElUSU9OX1JFSU5WT0tFX0RFTEFZX1NFQ09ORFMgPSAyO1xuXG4vKipcbiAqIEVmZmVjdGl2ZSBkZWxheSBiZWZvcmUgYSBwcmVjb25kaXRpb24gcmUtaW52b2NhdGlvbi4gT3ZlcnJpZGUgdmlhXG4gKiBgV09SS0ZMT1dfUFJFQ09ORElUSU9OX1JFSU5WT0tFX0RFTEFZX1NFQ09ORFNgLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0UHJlY29uZGl0aW9uUmVpbnZva2VEZWxheVNlY29uZHMoKTogbnVtYmVyIHtcbiAgcmV0dXJuIGVudk51bWJlcihcbiAgICAnV09SS0ZMT1dfUFJFQ09ORElUSU9OX1JFSU5WT0tFX0RFTEFZX1NFQ09ORFMnLFxuICAgIFBSRUNPTkRJVElPTl9SRUlOVk9LRV9ERUxBWV9TRUNPTkRTLFxuICAgIHsgaW50ZWdlcjogdHJ1ZSB9XG4gICk7XG59XG5cbi8vIEEgZGVsaXZlcnkgcmVhY2hpbmcgYSBkZXBsb3ltZW50IHRoZSBydW4gaXMgbm90IHBpbm5lZCB0byBpcyBub3QgdHJlYXRlZCBhc1xuLy8gcGVybWFuZW50LiBSZS1yb3V0ZSB0aGUgbWVzc2FnZSBhdCB0aGUgcnVuJ3Mgb3duIGRlcGxveW1lbnQgYSBib3VuZGVkIG51bWJlclxuLy8gb2YgdGltZXMgYmVmb3JlIGZhaWxpbmcgdGhlIHJ1biB3aXRoIERFUExPWU1FTlRfTUlTTUFUQ0guXG5leHBvcnQgY29uc3QgREVQTE9ZTUVOVF9NSVNNQVRDSF9NQVhfUkVUUklFUyA9IDM7XG5cbi8qKlxuICogRWZmZWN0aXZlIGRlcGxveW1lbnQtbWlzbWF0Y2ggcmUtcm91dGUgYnVkZ2V0LiBPdmVycmlkZSB2aWFcbiAqIGBXT1JLRkxPV19ERVBMT1lNRU5UX01JU01BVENIX01BWF9SRVRSSUVTYDsgYDBgIGZhaWxzIHRoZSBydW4gb24gdGhlIGZpcnN0XG4gKiBtaXNyb3V0ZWQgZGVsaXZlcnkgaW5zdGVhZCBvZiBhdHRlbXB0aW5nIHJlY292ZXJ5LlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0RGVwbG95bWVudE1pc21hdGNoTWF4UmV0cmllcygpOiBudW1iZXIge1xuICByZXR1cm4gZW52TnVtYmVyKFxuICAgICdXT1JLRkxPV19ERVBMT1lNRU5UX01JU01BVENIX01BWF9SRVRSSUVTJyxcbiAgICBERVBMT1lNRU5UX01JU01BVENIX01BWF9SRVRSSUVTLFxuICAgIHsgaW50ZWdlcjogdHJ1ZSwgbWluOiAwIH1cbiAgKTtcbn1cbiJdfQ==
|
|
@@ -2,16 +2,16 @@ import type { Event } from '@workflow/world';
|
|
|
2
2
|
/**
|
|
3
3
|
* Scope for {@link countStepStartedEvents}:
|
|
4
4
|
* - `{ type: 'ownedBy', messageId }` counts only starts whose
|
|
5
|
-
* `eventData.ownerMessageId` matches
|
|
5
|
+
* `eventData.ownerMessageId` matches, i.e. attempts performed by that
|
|
6
6
|
* owning queue message (inline lazy starts and owned-recovery re-stamps).
|
|
7
7
|
* - `{ type: 'totalAttempts' }` estimates the step's genuine attempt total
|
|
8
|
-
* across its whole lifecycle: unstamped (bare) starts
|
|
9
|
-
* queue-dispatched background deliveries write
|
|
8
|
+
* across its whole lifecycle: unstamped (bare) starts, which only real
|
|
9
|
+
* queue-dispatched background deliveries write, plus the starts of the
|
|
10
10
|
* single most-started owner. A genuine lifecycle has at most one inline
|
|
11
11
|
* owner phase (ownership is claimed atomically at step creation and
|
|
12
12
|
* lapses permanently at `step_retrying` or on any bare start), so taking
|
|
13
13
|
* the max over owners counts that phase's real attempts while invocations
|
|
14
|
-
* racing on the same batch
|
|
14
|
+
* racing on the same batch, which stamp their own one-off message IDs,
|
|
15
15
|
* contribute at most their single largest count instead of accumulating.
|
|
16
16
|
*/
|
|
17
17
|
export type StepStartScope = {
|
|
@@ -29,7 +29,7 @@ export type StepStartScope = {
|
|
|
29
29
|
* Concurrent invocations racing on the same pending batch (stale replays,
|
|
30
30
|
* wake replays, a step message dispatched by a replay that lost the
|
|
31
31
|
* create-claim race, ...) can each write a `step_started` for the same
|
|
32
|
-
* logical attempt
|
|
32
|
+
* logical attempt. Worlds without an atomic start guard (world-local) let
|
|
33
33
|
* all of them through. Counting those duplicates as "attempts" made the
|
|
34
34
|
* maxRetries ceiling fire on healthy runs and fail them with a false
|
|
35
35
|
* "exceeded max retries" (see workflow#3069).
|
|
@@ -37,11 +37,11 @@ export type StepStartScope = {
|
|
|
37
37
|
* Callers therefore scope the count to the starts their ceiling is actually
|
|
38
38
|
* about via `scope`:
|
|
39
39
|
* - the inline owned-recovery ceiling counts only THIS message's starts
|
|
40
|
-
* (`ownedBy`)
|
|
40
|
+
* (`ownedBy`): each real (re)delivery of the owning message stamps its
|
|
41
41
|
* `ownerMessageId` on the start it writes, while racing invocations stamp
|
|
42
42
|
* their own IDs (or none), so they no longer inflate the count;
|
|
43
43
|
* - the background-step ceiling counts the lifecycle attempt total
|
|
44
|
-
* (`totalAttempts`: bare starts plus the largest single owner's starts)
|
|
44
|
+
* (`totalAttempts`: bare starts plus the largest single owner's starts),
|
|
45
45
|
* so a step that exhausted part of its budget under inline ownership
|
|
46
46
|
* before transitioning to queued/bare retries still trips the combined
|
|
47
47
|
* ceiling, while racers' one-off stamped duplicates don't accumulate, and
|
|
@@ -13,7 +13,7 @@ const ownerOf = (e) => 'eventData' in e &&
|
|
|
13
13
|
* Concurrent invocations racing on the same pending batch (stale replays,
|
|
14
14
|
* wake replays, a step message dispatched by a replay that lost the
|
|
15
15
|
* create-claim race, ...) can each write a `step_started` for the same
|
|
16
|
-
* logical attempt
|
|
16
|
+
* logical attempt. Worlds without an atomic start guard (world-local) let
|
|
17
17
|
* all of them through. Counting those duplicates as "attempts" made the
|
|
18
18
|
* maxRetries ceiling fire on healthy runs and fail them with a false
|
|
19
19
|
* "exceeded max retries" (see workflow#3069).
|
|
@@ -21,11 +21,11 @@ const ownerOf = (e) => 'eventData' in e &&
|
|
|
21
21
|
* Callers therefore scope the count to the starts their ceiling is actually
|
|
22
22
|
* about via `scope`:
|
|
23
23
|
* - the inline owned-recovery ceiling counts only THIS message's starts
|
|
24
|
-
* (`ownedBy`)
|
|
24
|
+
* (`ownedBy`): each real (re)delivery of the owning message stamps its
|
|
25
25
|
* `ownerMessageId` on the start it writes, while racing invocations stamp
|
|
26
26
|
* their own IDs (or none), so they no longer inflate the count;
|
|
27
27
|
* - the background-step ceiling counts the lifecycle attempt total
|
|
28
|
-
* (`totalAttempts`: bare starts plus the largest single owner's starts)
|
|
28
|
+
* (`totalAttempts`: bare starts plus the largest single owner's starts),
|
|
29
29
|
* so a step that exhausted part of its budget under inline ownership
|
|
30
30
|
* before transitioning to queued/bare retries still trips the combined
|
|
31
31
|
* ceiling, while racers' one-off stamped duplicates don't accumulate, and
|
|
@@ -69,4 +69,4 @@ export function countStepStartedEvents(events, stepId, scope) {
|
|
|
69
69
|
}
|
|
70
70
|
return bare + maxOwner;
|
|
71
71
|
}
|
|
72
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
72
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY291bnQtc3RlcC1zdGFydGVkLWV2ZW50cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ydW50aW1lL2NvdW50LXN0ZXAtc3RhcnRlZC1ldmVudHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBcUJBLE1BQU0sT0FBTyxHQUFHLENBQUMsQ0FBUSxFQUFzQixFQUFFLENBQy9DLFdBQVcsSUFBSSxDQUFDO0lBQ2hCLENBQUMsQ0FBQyxTQUFTO0lBQ1gsZ0JBQWdCLElBQUksQ0FBQyxDQUFDLFNBQVM7SUFDL0IsT0FBTyxDQUFDLENBQUMsU0FBUyxDQUFDLGNBQWMsS0FBSyxRQUFRO0lBQzVDLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLGNBQWM7SUFDNUIsQ0FBQyxDQUFDLFNBQVMsQ0FBQztBQUVoQjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBMkJHO0FBQ0gsTUFBTSxVQUFVLHNCQUFzQixDQUNwQyxNQUFrQyxFQUNsQyxNQUFjLEVBQ2QsS0FBc0I7SUFFdEIsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ1osT0FBTyxDQUFDLENBQUM7SUFDWCxDQUFDO0lBQ0QsSUFBSSxJQUFJLEdBQUcsQ0FBQyxDQUFDO0lBQ2IsTUFBTSxPQUFPLEdBQUcsSUFBSSxHQUFHLEVBQWtCLENBQUM7SUFDMUMsS0FBSyxNQUFNLENBQUMsSUFBSSxNQUFNLEVBQUUsQ0FBQztRQUN2QixJQUFJLENBQUMsQ0FBQyxTQUFTLEtBQUssY0FBYyxJQUFJLENBQUMsQ0FBQyxhQUFhLEtBQUssTUFBTSxFQUFFLENBQUM7WUFDakUsU0FBUztRQUNYLENBQUM7UUFDRCxNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDekIsSUFBSSxLQUFLLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDeEIsSUFBSSxFQUFFLENBQUM7UUFDVCxDQUFDO2FBQU0sQ0FBQztZQUNOLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUNwRCxDQUFDO0lBQ0gsQ0FBQztJQUNELElBQUksS0FBSyxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQ3hCLElBQUksS0FBSyxHQUFHLElBQUksQ0FBQztRQUNqQixLQUFLLE1BQU0sS0FBSyxJQUFJLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDO1lBQ3JDLEtBQUssSUFBSSxLQUFLLENBQUM7UUFDakIsQ0FBQztRQUNELE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUNELElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUM3QixPQUFPLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMzQyxDQUFDO0lBQ0QsZ0JBQWdCO0lBQ2hCLElBQUksUUFBUSxHQUFHLENBQUMsQ0FBQztJQUNqQixLQUFLLE1BQU0sS0FBSyxJQUFJLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDO1FBQ3JDLElBQUksS0FBSyxHQUFHLFFBQVEsRUFBRSxDQUFDO1lBQ3JCLFFBQVEsR0FBRyxLQUFLLENBQUM7UUFDbkIsQ0FBQztJQUNILENBQUM7SUFDRCxPQUFPLElBQUksR0FBRyxRQUFRLENBQUM7QUFDekIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgRXZlbnQgfSBmcm9tICdAd29ya2Zsb3cvd29ybGQnO1xuXG4vKipcbiAqIFNjb3BlIGZvciB7QGxpbmsgY291bnRTdGVwU3RhcnRlZEV2ZW50c306XG4gKiAtIGB7IHR5cGU6ICdvd25lZEJ5JywgbWVzc2FnZUlkIH1gIGNvdW50cyBvbmx5IHN0YXJ0cyB3aG9zZVxuICogICBgZXZlbnREYXRhLm93bmVyTWVzc2FnZUlkYCBtYXRjaGVzLCBpLmUuIGF0dGVtcHRzIHBlcmZvcm1lZCBieSB0aGF0XG4gKiAgIG93bmluZyBxdWV1ZSBtZXNzYWdlIChpbmxpbmUgbGF6eSBzdGFydHMgYW5kIG93bmVkLXJlY292ZXJ5IHJlLXN0YW1wcykuXG4gKiAtIGB7IHR5cGU6ICd0b3RhbEF0dGVtcHRzJyB9YCBlc3RpbWF0ZXMgdGhlIHN0ZXAncyBnZW51aW5lIGF0dGVtcHQgdG90YWxcbiAqICAgYWNyb3NzIGl0cyB3aG9sZSBsaWZlY3ljbGU6IHVuc3RhbXBlZCAoYmFyZSkgc3RhcnRzLCB3aGljaCBvbmx5IHJlYWxcbiAqICAgcXVldWUtZGlzcGF0Y2hlZCBiYWNrZ3JvdW5kIGRlbGl2ZXJpZXMgd3JpdGUsIHBsdXMgdGhlIHN0YXJ0cyBvZiB0aGVcbiAqICAgc2luZ2xlIG1vc3Qtc3RhcnRlZCBvd25lci4gQSBnZW51aW5lIGxpZmVjeWNsZSBoYXMgYXQgbW9zdCBvbmUgaW5saW5lXG4gKiAgIG93bmVyIHBoYXNlIChvd25lcnNoaXAgaXMgY2xhaW1lZCBhdG9taWNhbGx5IGF0IHN0ZXAgY3JlYXRpb24gYW5kXG4gKiAgIGxhcHNlcyBwZXJtYW5lbnRseSBhdCBgc3RlcF9yZXRyeWluZ2Agb3Igb24gYW55IGJhcmUgc3RhcnQpLCBzbyB0YWtpbmdcbiAqICAgdGhlIG1heCBvdmVyIG93bmVycyBjb3VudHMgdGhhdCBwaGFzZSdzIHJlYWwgYXR0ZW1wdHMgd2hpbGUgaW52b2NhdGlvbnNcbiAqICAgcmFjaW5nIG9uIHRoZSBzYW1lIGJhdGNoLCB3aGljaCBzdGFtcCB0aGVpciBvd24gb25lLW9mZiBtZXNzYWdlIElEcyxcbiAqICAgY29udHJpYnV0ZSBhdCBtb3N0IHRoZWlyIHNpbmdsZSBsYXJnZXN0IGNvdW50IGluc3RlYWQgb2YgYWNjdW11bGF0aW5nLlxuICovXG5leHBvcnQgdHlwZSBTdGVwU3RhcnRTY29wZSA9XG4gIHwgeyB0eXBlOiAnb3duZWRCeSc7IG1lc3NhZ2VJZDogc3RyaW5nIH1cbiAgfCB7IHR5cGU6ICd0b3RhbEF0dGVtcHRzJyB9O1xuXG5jb25zdCBvd25lck9mID0gKGU6IEV2ZW50KTogc3RyaW5nIHwgdW5kZWZpbmVkID0+XG4gICdldmVudERhdGEnIGluIGUgJiZcbiAgZS5ldmVudERhdGEgJiZcbiAgJ293bmVyTWVzc2FnZUlkJyBpbiBlLmV2ZW50RGF0YSAmJlxuICB0eXBlb2YgZS5ldmVudERhdGEub3duZXJNZXNzYWdlSWQgPT09ICdzdHJpbmcnXG4gICAgPyBlLmV2ZW50RGF0YS5vd25lck1lc3NhZ2VJZFxuICAgIDogdW5kZWZpbmVkO1xuXG4vKipcbiAqIE51bWJlciBvZiBgc3RlcF9zdGFydGVkYCBldmVudHMgYWxyZWFkeSByZWNvcmRlZCBmb3IgYSBzdGVwLCB1c2VkIGFzIHRoZVxuICogYXV0aG9yaXRhdGl2ZSBhdHRlbXB0IGNvdW50IGZvciB0aGUgbWF4UmV0cmllcyBjZWlsaW5nICh0aGUgb25seSBib3VuZCBmb3JcbiAqIHN0ZXBzIHRoYXQgdGltZSBvdXQgd2l0aG91dCB3cml0aW5nIGEgYHN0ZXBfZmFpbGVkYCkuXG4gKlxuICogSU1QT1JUQU5UOiB0aGUgcmF3ICh1bnNjb3BlZCkgY291bnQgaXMgTk9UIGEgcmVsaWFibGUgYXR0ZW1wdCBudW1iZXIuXG4gKiBDb25jdXJyZW50IGludm9jYXRpb25zIHJhY2luZyBvbiB0aGUgc2FtZSBwZW5kaW5nIGJhdGNoIChzdGFsZSByZXBsYXlzLFxuICogd2FrZSByZXBsYXlzLCBhIHN0ZXAgbWVzc2FnZSBkaXNwYXRjaGVkIGJ5IGEgcmVwbGF5IHRoYXQgbG9zdCB0aGVcbiAqIGNyZWF0ZS1jbGFpbSByYWNlLCAuLi4pIGNhbiBlYWNoIHdyaXRlIGEgYHN0ZXBfc3RhcnRlZGAgZm9yIHRoZSBzYW1lXG4gKiBsb2dpY2FsIGF0dGVtcHQuIFdvcmxkcyB3aXRob3V0IGFuIGF0b21pYyBzdGFydCBndWFyZCAod29ybGQtbG9jYWwpIGxldFxuICogYWxsIG9mIHRoZW0gdGhyb3VnaC4gQ291bnRpbmcgdGhvc2UgZHVwbGljYXRlcyBhcyBcImF0dGVtcHRzXCIgbWFkZSB0aGVcbiAqIG1heFJldHJpZXMgY2VpbGluZyBmaXJlIG9uIGhlYWx0aHkgcnVucyBhbmQgZmFpbCB0aGVtIHdpdGggYSBmYWxzZVxuICogXCJleGNlZWRlZCBtYXggcmV0cmllc1wiIChzZWUgd29ya2Zsb3cjMzA2OSkuXG4gKlxuICogQ2FsbGVycyB0aGVyZWZvcmUgc2NvcGUgdGhlIGNvdW50IHRvIHRoZSBzdGFydHMgdGhlaXIgY2VpbGluZyBpcyBhY3R1YWxseVxuICogYWJvdXQgdmlhIGBzY29wZWA6XG4gKiAtIHRoZSBpbmxpbmUgb3duZWQtcmVjb3ZlcnkgY2VpbGluZyBjb3VudHMgb25seSBUSElTIG1lc3NhZ2UncyBzdGFydHNcbiAqICAgKGBvd25lZEJ5YCk6IGVhY2ggcmVhbCAocmUpZGVsaXZlcnkgb2YgdGhlIG93bmluZyBtZXNzYWdlIHN0YW1wcyBpdHNcbiAqICAgYG93bmVyTWVzc2FnZUlkYCBvbiB0aGUgc3RhcnQgaXQgd3JpdGVzLCB3aGlsZSByYWNpbmcgaW52b2NhdGlvbnMgc3RhbXBcbiAqICAgdGhlaXIgb3duIElEcyAob3Igbm9uZSksIHNvIHRoZXkgbm8gbG9uZ2VyIGluZmxhdGUgdGhlIGNvdW50O1xuICogLSB0aGUgYmFja2dyb3VuZC1zdGVwIGNlaWxpbmcgY291bnRzIHRoZSBsaWZlY3ljbGUgYXR0ZW1wdCB0b3RhbFxuICogICAoYHRvdGFsQXR0ZW1wdHNgOiBiYXJlIHN0YXJ0cyBwbHVzIHRoZSBsYXJnZXN0IHNpbmdsZSBvd25lcidzIHN0YXJ0cyksXG4gKiAgIHNvIGEgc3RlcCB0aGF0IGV4aGF1c3RlZCBwYXJ0IG9mIGl0cyBidWRnZXQgdW5kZXIgaW5saW5lIG93bmVyc2hpcFxuICogICBiZWZvcmUgdHJhbnNpdGlvbmluZyB0byBxdWV1ZWQvYmFyZSByZXRyaWVzIHN0aWxsIHRyaXBzIHRoZSBjb21iaW5lZFxuICogICBjZWlsaW5nLCB3aGlsZSByYWNlcnMnIG9uZS1vZmYgc3RhbXBlZCBkdXBsaWNhdGVzIGRvbid0IGFjY3VtdWxhdGUsIGFuZFxuICogICB0aHJvdHRsZS90b28tZWFybHkgcmVkZWxpdmVyaWVzICh3aGljaCB3cml0ZSBubyBzdGFydCBhdCBhbGwpIHN0YXlcbiAqICAgZXhjbHVkZWQgYXMgYmVmb3JlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY291bnRTdGVwU3RhcnRlZEV2ZW50cyhcbiAgZXZlbnRzOiBFdmVudFtdIHwgbnVsbCB8IHVuZGVmaW5lZCxcbiAgc3RlcElkOiBzdHJpbmcsXG4gIHNjb3BlPzogU3RlcFN0YXJ0U2NvcGVcbik6IG51bWJlciB7XG4gIGlmICghZXZlbnRzKSB7XG4gICAgcmV0dXJuIDA7XG4gIH1cbiAgbGV0IGJhcmUgPSAwO1xuICBjb25zdCBieU93bmVyID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcj4oKTtcbiAgZm9yIChjb25zdCBlIG9mIGV2ZW50cykge1xuICAgIGlmIChlLmV2ZW50VHlwZSAhPT0gJ3N0ZXBfc3RhcnRlZCcgfHwgZS5jb3JyZWxhdGlvbklkICE9PSBzdGVwSWQpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBjb25zdCBvd25lciA9IG93bmVyT2YoZSk7XG4gICAgaWYgKG93bmVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGJhcmUrKztcbiAgICB9IGVsc2Uge1xuICAgICAgYnlPd25lci5zZXQob3duZXIsIChieU93bmVyLmdldChvd25lcikgPz8gMCkgKyAxKTtcbiAgICB9XG4gIH1cbiAgaWYgKHNjb3BlID09PSB1bmRlZmluZWQpIHtcbiAgICBsZXQgdG90YWwgPSBiYXJlO1xuICAgIGZvciAoY29uc3QgY291bnQgb2YgYnlPd25lci52YWx1ZXMoKSkge1xuICAgICAgdG90YWwgKz0gY291bnQ7XG4gICAgfVxuICAgIHJldHVybiB0b3RhbDtcbiAgfVxuICBpZiAoc2NvcGUudHlwZSA9PT0gJ293bmVkQnknKSB7XG4gICAgcmV0dXJuIGJ5T3duZXIuZ2V0KHNjb3BlLm1lc3NhZ2VJZCkgPz8gMDtcbiAgfVxuICAvLyB0b3RhbEF0dGVtcHRzXG4gIGxldCBtYXhPd25lciA9IDA7XG4gIGZvciAoY29uc3QgY291bnQgb2YgYnlPd25lci52YWx1ZXMoKSkge1xuICAgIGlmIChjb3VudCA+IG1heE93bmVyKSB7XG4gICAgICBtYXhPd25lciA9IGNvdW50O1xuICAgIH1cbiAgfVxuICByZXR1cm4gYmFyZSArIG1heE93bmVyO1xufVxuIl19
|