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