@workflow/core 5.0.0-beta.3 → 5.0.0-beta.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/attribute-changes.d.ts +7 -0
- package/dist/attribute-changes.d.ts.map +1 -0
- package/dist/attribute-changes.js +25 -0
- package/dist/capabilities.d.ts +22 -1
- package/dist/capabilities.d.ts.map +1 -1
- package/dist/capabilities.js +41 -4
- package/dist/capture-stack.d.ts +16 -0
- package/dist/capture-stack.d.ts.map +1 -0
- package/dist/capture-stack.js +21 -0
- 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 +26 -3
- package/dist/classify-error.d.ts.map +1 -1
- package/dist/classify-error.js +103 -6
- package/dist/context-errors.d.ts +27 -0
- package/dist/context-errors.d.ts.map +1 -0
- package/dist/context-errors.js +101 -0
- package/dist/context-violation-error.d.ts +97 -0
- package/dist/context-violation-error.d.ts.map +1 -0
- package/dist/context-violation-error.js +147 -0
- package/dist/create-hook.d.ts +42 -3
- package/dist/create-hook.d.ts.map +1 -1
- package/dist/create-hook.js +4 -3
- package/dist/define-hook.d.ts.map +1 -1
- package/dist/define-hook.js +20 -5
- package/dist/describe-error.d.ts +70 -0
- package/dist/describe-error.d.ts.map +1 -0
- package/dist/describe-error.js +165 -0
- package/dist/encryption.d.ts +22 -1
- package/dist/encryption.d.ts.map +1 -1
- package/dist/encryption.js +72 -27
- package/dist/events-consumer.d.ts +25 -1
- package/dist/events-consumer.d.ts.map +1 -1
- package/dist/events-consumer.js +95 -16
- package/dist/flushable-stream.d.ts +10 -10
- package/dist/flushable-stream.d.ts.map +1 -1
- package/dist/flushable-stream.js +26 -15
- package/dist/global.d.ts +35 -1
- package/dist/global.d.ts.map +1 -1
- package/dist/global.js +21 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/log-format.d.ts +25 -0
- package/dist/log-format.d.ts.map +1 -0
- package/dist/log-format.js +250 -0
- package/dist/logger.d.ts +29 -30
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +82 -32
- package/dist/private.d.ts +107 -2
- package/dist/private.d.ts.map +1 -1
- package/dist/private.js +80 -3
- package/dist/runtime/constants.d.ts +189 -0
- package/dist/runtime/constants.d.ts.map +1 -1
- package/dist/runtime/constants.js +310 -15
- package/dist/runtime/get-port-lazy.d.ts +25 -0
- package/dist/runtime/get-port-lazy.d.ts.map +1 -0
- package/dist/runtime/get-port-lazy.js +92 -0
- package/dist/runtime/get-world-lazy.d.ts +23 -0
- package/dist/runtime/get-world-lazy.d.ts.map +1 -0
- package/dist/runtime/get-world-lazy.js +46 -0
- package/dist/runtime/helpers.d.ts +57 -6
- package/dist/runtime/helpers.d.ts.map +1 -1
- package/dist/runtime/helpers.js +169 -32
- package/dist/runtime/replay-budget.d.ts +98 -0
- package/dist/runtime/replay-budget.d.ts.map +1 -0
- package/dist/runtime/replay-budget.js +192 -0
- package/dist/runtime/resume-hook.d.ts.map +1 -1
- package/dist/runtime/resume-hook.js +39 -23
- package/dist/runtime/run-id-time.d.ts +10 -0
- package/dist/runtime/run-id-time.d.ts.map +1 -0
- package/dist/runtime/run-id-time.js +31 -0
- package/dist/runtime/run.d.ts +6 -2
- package/dist/runtime/run.d.ts.map +1 -1
- package/dist/runtime/run.js +52 -10
- package/dist/runtime/runs.d.ts +36 -2
- package/dist/runtime/runs.d.ts.map +1 -1
- package/dist/runtime/runs.js +18 -7
- package/dist/runtime/start.d.ts +58 -1
- package/dist/runtime/start.d.ts.map +1 -1
- package/dist/runtime/start.js +160 -46
- package/dist/runtime/step-executor.d.ts +131 -0
- package/dist/runtime/step-executor.d.ts.map +1 -0
- package/dist/runtime/step-executor.js +818 -0
- package/dist/runtime/step-handler.d.ts.map +1 -1
- package/dist/runtime/step-handler.js +718 -557
- package/dist/runtime/step-latency.d.ts +131 -0
- package/dist/runtime/step-latency.d.ts.map +1 -0
- package/dist/runtime/step-latency.js +155 -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 +69 -0
- package/dist/runtime/suspension-handler.d.ts +81 -7
- package/dist/runtime/suspension-handler.d.ts.map +1 -1
- package/dist/runtime/suspension-handler.js +355 -137
- package/dist/runtime/wait-continuation.d.ts +84 -0
- package/dist/runtime/wait-continuation.d.ts.map +1 -0
- package/dist/runtime/wait-continuation.js +105 -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 +5 -0
- package/dist/runtime/world-compatibility.d.ts.map +1 -0
- package/dist/runtime/world-compatibility.js +12 -0
- package/dist/runtime/world-init.d.ts +50 -0
- package/dist/runtime/world-init.d.ts.map +1 -0
- package/dist/runtime/world-init.js +50 -0
- package/dist/runtime/world-target.d.ts +11 -0
- package/dist/runtime/world-target.d.ts.map +1 -0
- package/dist/runtime/world-target.js +15 -0
- package/dist/runtime/world.d.ts +21 -9
- package/dist/runtime/world.d.ts.map +1 -1
- package/dist/runtime/world.js +58 -83
- package/dist/runtime.d.ts +15 -10
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +1757 -326
- package/dist/schemas.d.ts +1 -1
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +1 -1
- package/dist/serialization/client.d.ts +17 -0
- package/dist/serialization/client.d.ts.map +1 -0
- package/dist/serialization/client.js +48 -0
- package/dist/serialization/codec-devalue.d.ts +14 -0
- package/dist/serialization/codec-devalue.d.ts.map +1 -0
- package/dist/serialization/codec-devalue.js +98 -0
- package/dist/serialization/codec.d.ts +106 -0
- package/dist/serialization/codec.d.ts.map +1 -0
- package/dist/serialization/codec.js +17 -0
- package/dist/serialization/compression.d.ts +104 -0
- package/dist/serialization/compression.d.ts.map +1 -0
- package/dist/serialization/compression.js +260 -0
- package/dist/serialization/encryption.d.ts +33 -0
- package/dist/serialization/encryption.d.ts.map +1 -0
- package/dist/serialization/encryption.js +70 -0
- package/dist/serialization/errors.d.ts +34 -0
- package/dist/serialization/errors.d.ts.map +1 -0
- package/dist/serialization/errors.js +59 -0
- package/dist/serialization/format.d.ts +60 -0
- package/dist/serialization/format.d.ts.map +1 -0
- package/dist/serialization/format.js +97 -0
- package/dist/serialization/index.d.ts +19 -0
- package/dist/serialization/index.d.ts.map +1 -0
- package/dist/serialization/index.js +22 -0
- package/dist/serialization/reducers/class.d.ts +11 -0
- package/dist/serialization/reducers/class.d.ts.map +1 -0
- package/dist/serialization/reducers/class.js +68 -0
- package/dist/serialization/reducers/common.d.ts +16 -0
- package/dist/serialization/reducers/common.d.ts.map +1 -0
- package/dist/serialization/reducers/common.js +417 -0
- package/dist/serialization/reducers/step-function.d.ts +35 -0
- package/dist/serialization/reducers/step-function.d.ts.map +1 -0
- package/dist/serialization/reducers/step-function.js +88 -0
- package/dist/serialization/step.d.ts +17 -0
- package/dist/serialization/step.d.ts.map +1 -0
- package/dist/serialization/step.js +48 -0
- package/dist/serialization/types.d.ts +253 -0
- package/dist/serialization/types.d.ts.map +1 -0
- package/dist/serialization/types.js +25 -0
- package/dist/serialization/workflow.d.ts +29 -0
- package/dist/serialization/workflow.d.ts.map +1 -0
- package/dist/serialization/workflow.js +54 -0
- package/dist/serialization-format.d.ts +16 -0
- package/dist/serialization-format.d.ts.map +1 -1
- package/dist/serialization-format.js +213 -50
- package/dist/serialization.d.ts +322 -214
- package/dist/serialization.d.ts.map +1 -1
- package/dist/serialization.js +1575 -664
- package/dist/set-attributes.d.ts +18 -0
- package/dist/set-attributes.d.ts.map +1 -0
- package/dist/set-attributes.js +61 -0
- package/dist/sleep.d.ts.map +1 -1
- package/dist/sleep.js +3 -2
- package/dist/source-map.d.ts +5 -0
- package/dist/source-map.d.ts.map +1 -1
- package/dist/source-map.js +102 -10
- package/dist/step/context-storage.d.ts +53 -0
- package/dist/step/context-storage.d.ts.map +1 -1
- package/dist/step/context-storage.js +1 -1
- package/dist/step/get-closure-vars.d.ts.map +1 -1
- package/dist/step/get-closure-vars.js +3 -2
- package/dist/step/get-step-metadata.d.ts.map +1 -1
- package/dist/step/get-step-metadata.js +3 -2
- package/dist/step/get-workflow-metadata.d.ts.map +1 -1
- package/dist/step/get-workflow-metadata.js +3 -2
- package/dist/step/writable-stream.d.ts.map +1 -1
- package/dist/step/writable-stream.js +58 -6
- package/dist/step-hydration-cache.d.ts +148 -0
- package/dist/step-hydration-cache.d.ts.map +1 -0
- package/dist/step-hydration-cache.js +171 -0
- package/dist/step.d.ts.map +1 -1
- package/dist/step.js +144 -25
- package/dist/symbols.d.ts +28 -0
- package/dist/symbols.d.ts.map +1 -1
- package/dist/symbols.js +29 -1
- package/dist/telemetry/semantic-conventions.d.ts +98 -2
- package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
- package/dist/telemetry/semantic-conventions.js +66 -1
- package/dist/telemetry.d.ts +68 -0
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +106 -4
- 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 +16 -6
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +25 -16
- 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 +3 -2
- package/dist/vm/script-cache.d.ts +28 -0
- package/dist/vm/script-cache.d.ts.map +1 -0
- package/dist/vm/script-cache.js +140 -0
- package/dist/workflow/abort-controller.d.ts +65 -0
- package/dist/workflow/abort-controller.d.ts.map +1 -0
- package/dist/workflow/abort-controller.js +277 -0
- 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 +48 -0
- package/dist/workflow/create-hook.d.ts.map +1 -1
- package/dist/workflow/create-hook.js +25 -3
- package/dist/workflow/define-hook.d.ts +1 -1
- package/dist/workflow/define-hook.d.ts.map +1 -1
- package/dist/workflow/define-hook.js +8 -4
- package/dist/workflow/get-workflow-metadata.d.ts.map +1 -1
- package/dist/workflow/get-workflow-metadata.js +14 -3
- package/dist/workflow/hook.d.ts.map +1 -1
- package/dist/workflow/hook.js +207 -33
- package/dist/workflow/index.d.ts +1 -0
- package/dist/workflow/index.d.ts.map +1 -1
- package/dist/workflow/index.js +5 -3
- package/dist/workflow/set-attributes.d.ts +77 -0
- package/dist/workflow/set-attributes.d.ts.map +1 -0
- package/dist/workflow/set-attributes.js +65 -0
- package/dist/workflow/sleep.d.ts.map +1 -1
- package/dist/workflow/sleep.js +45 -8
- package/dist/workflow/world-init-stub.d.ts +15 -0
- package/dist/workflow/world-init-stub.d.ts.map +1 -0
- package/dist/workflow/world-init-stub.js +15 -0
- package/dist/workflow.d.ts +17 -1
- package/dist/workflow.d.ts.map +1 -1
- package/dist/workflow.js +190 -56
- package/docs/api-reference/create-hook.mdx +38 -0
- package/docs/api-reference/create-webhook.mdx +1 -0
- package/docs/api-reference/fetch.mdx +5 -0
- package/docs/api-reference/index.mdx +3 -0
- package/docs/api-reference/set-attributes.mdx +65 -0
- package/docs/foundations/cancellation.mdx +459 -0
- package/docs/foundations/errors-and-retries.mdx +7 -3
- package/docs/foundations/hooks.mdx +29 -0
- package/docs/foundations/idempotency.mdx +236 -11
- package/docs/foundations/index.mdx +1 -23
- package/docs/foundations/meta.json +3 -1
- package/docs/foundations/serialization.mdx +77 -41
- package/docs/foundations/starting-workflows.mdx +5 -1
- package/docs/foundations/streaming.mdx +14 -23
- package/docs/foundations/versioning.mdx +263 -0
- package/docs/how-it-works/cancellation.mdx +287 -0
- package/docs/how-it-works/code-transform.mdx +2 -2
- package/docs/how-it-works/encryption.mdx +2 -2
- package/docs/how-it-works/event-sourcing.mdx +2 -2
- package/docs/how-it-works/meta.json +2 -1
- package/package.json +32 -11
|
@@ -1,128 +1,246 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { SPEC_VERSION_CURRENT, } from '@workflow/world';
|
|
1
|
+
import { EntityConflictError, FatalError, HookNotFoundError, RunExpiredError, WorkflowWorldError, } from '@workflow/errors';
|
|
2
|
+
import { AttributeValidationError, SPEC_VERSION_CURRENT, SPEC_VERSION_SUPPORTS_COMPRESSION, } from '@workflow/world';
|
|
4
3
|
import { importKey } from '../encryption.js';
|
|
5
4
|
import { runtimeLogger } from '../logger.js';
|
|
6
5
|
import { dehydrateStepArguments } from '../serialization.js';
|
|
7
6
|
import * as Attribute from '../telemetry/semantic-conventions.js';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
7
|
+
import { getAbortStreamIdFromToken } from '../util.js';
|
|
8
|
+
import { getMaxInlineSteps } from './constants.js';
|
|
9
|
+
async function createHookEvent({ world, runId, hookEvent, queueItem, requestId, }) {
|
|
10
|
+
try {
|
|
11
|
+
const result = await world.events.create(runId, hookEvent, {
|
|
12
|
+
requestId,
|
|
13
|
+
});
|
|
14
|
+
// Check if the world returned a hook_conflict event instead of hook_created.
|
|
15
|
+
// The hook_conflict event is stored in the event log and will be replayed
|
|
16
|
+
// on the next workflow invocation, causing the hook's promise to reject.
|
|
17
|
+
if (result.event?.eventType === 'hook_conflict') {
|
|
18
|
+
return {
|
|
19
|
+
hasHookConflict: true,
|
|
20
|
+
hasAwaitedHookCreation: false,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
hasHookConflict: false,
|
|
25
|
+
hasAwaitedHookCreation: queueItem.hasConflictAwaiter === true,
|
|
26
|
+
};
|
|
18
27
|
}
|
|
19
|
-
|
|
20
|
-
|
|
28
|
+
catch (err) {
|
|
29
|
+
if (EntityConflictError.is(err)) {
|
|
30
|
+
runtimeLogger.info('Hook already exists, continuing', {
|
|
31
|
+
workflowRunId: runId,
|
|
32
|
+
message: err.message,
|
|
33
|
+
});
|
|
34
|
+
return {
|
|
35
|
+
hasHookConflict: false,
|
|
36
|
+
hasAwaitedHookCreation: queueItem.hasConflictAwaiter === true,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
if (RunExpiredError.is(err)) {
|
|
40
|
+
runtimeLogger.info('Workflow run already completed, skipping hook', {
|
|
41
|
+
workflowRunId: runId,
|
|
42
|
+
message: err.message,
|
|
43
|
+
});
|
|
44
|
+
return {
|
|
45
|
+
hasHookConflict: false,
|
|
46
|
+
hasAwaitedHookCreation: false,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
throw err;
|
|
21
50
|
}
|
|
22
|
-
return headers;
|
|
23
51
|
}
|
|
24
52
|
/**
|
|
25
53
|
* Handles a workflow suspension by processing all pending operations (hooks, steps, waits).
|
|
26
|
-
*
|
|
27
|
-
*
|
|
54
|
+
* Creates events for all operations but does NOT queue step messages — returns the pending
|
|
55
|
+
* steps so the caller can decide which to execute inline vs queue to background.
|
|
28
56
|
*
|
|
29
57
|
* Processing order:
|
|
30
58
|
* 1. Hooks are processed first to prevent race conditions with webhook receivers
|
|
31
|
-
* 2.
|
|
59
|
+
* 2. Step events and wait events are created in parallel
|
|
32
60
|
*/
|
|
33
|
-
export async function handleSuspension({ suspension, world, run, span, requestId, }) {
|
|
61
|
+
export async function handleSuspension({ suspension, world, run, span, requestId, runReadyBarrier, }) {
|
|
34
62
|
const runId = run.runId;
|
|
35
|
-
|
|
36
|
-
|
|
63
|
+
// Turbo mode: hold every world write below until the backgrounded
|
|
64
|
+
// `run_started` has *settled*, so we never write a step/hook/wait event for a
|
|
65
|
+
// run that does not exist yet. A no-op outside turbo (barrier undefined) and
|
|
66
|
+
// on the pure inline hot path, which defers all steps and writes nothing.
|
|
67
|
+
// Awaiting the same (usually already-settled) promise more than once is cheap.
|
|
68
|
+
// A barrier rejection is swallowed for ordering only: if `run_started` truly
|
|
69
|
+
// failed the run does not exist, so the subsequent write surfaces the real
|
|
70
|
+
// error (run not found / gone) and the message redelivers.
|
|
71
|
+
const ensureRunReady = async () => {
|
|
72
|
+
if (runReadyBarrier) {
|
|
73
|
+
try {
|
|
74
|
+
await runReadyBarrier;
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
// intentional: ordering barrier only — see above.
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
};
|
|
37
81
|
// Separate queue items by type
|
|
38
82
|
const stepItems = suspension.steps.filter((item) => item.type === 'step');
|
|
39
83
|
const allHookItems = suspension.steps.filter((item) => item.type === 'hook');
|
|
40
84
|
const waitItems = suspension.steps.filter((item) => item.type === 'wait');
|
|
41
|
-
|
|
85
|
+
const attributeItems = suspension.steps.filter((item) => item.type === 'attribute');
|
|
42
86
|
const hooksNeedingCreation = allHookItems.filter((item) => !item.hasCreatedEvent);
|
|
43
|
-
//
|
|
44
|
-
//
|
|
45
|
-
|
|
87
|
+
// Group hook items that need work by token, preserving queue-insertion
|
|
88
|
+
// (workflow code) order within each token. Operations on one token must
|
|
89
|
+
// apply in code order: a dispose() of an earlier hook releases the token
|
|
90
|
+
// before a later same-token hook's creation is validated — otherwise the
|
|
91
|
+
// new hook records a spurious hook_conflict against the run's own
|
|
92
|
+
// disposed hook — while a hook created and disposed within the same
|
|
93
|
+
// suspension is still created before it is disposed. Different tokens
|
|
94
|
+
// have no claim interaction, so token groups are processed in parallel.
|
|
95
|
+
const hookItemsByToken = new Map();
|
|
96
|
+
for (const item of allHookItems) {
|
|
97
|
+
if (item.hasCreatedEvent && !item.disposed) {
|
|
98
|
+
continue; // already committed and still live — nothing to do
|
|
99
|
+
}
|
|
100
|
+
const group = hookItemsByToken.get(item.token);
|
|
101
|
+
if (group) {
|
|
102
|
+
group.push(item);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
hookItemsByToken.set(item.token, [item]);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
46
108
|
// Resolve encryption key for this run
|
|
47
109
|
const rawKey = await world.getEncryptionKeyForRun?.(run);
|
|
48
110
|
const encryptionKey = rawKey ? await importKey(rawKey) : undefined;
|
|
49
|
-
//
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
eventType: 'hook_created',
|
|
111
|
+
// Gate payload compression on the run's specVersion: only runs marked
|
|
112
|
+
// as possibly containing compressed payloads (spec >= 5) get gzip data.
|
|
113
|
+
const compression = (run.specVersion ?? 0) >= SPEC_VERSION_SUPPORTS_COMPRESSION;
|
|
114
|
+
async function disposeHook(queueItem) {
|
|
115
|
+
const hookDisposedEvent = {
|
|
116
|
+
eventType: 'hook_disposed',
|
|
56
117
|
specVersion: SPEC_VERSION_CURRENT,
|
|
57
118
|
correlationId: queueItem.correlationId,
|
|
58
119
|
eventData: {
|
|
59
120
|
token: queueItem.token,
|
|
60
|
-
metadata: hookMetadata,
|
|
61
|
-
isWebhook: queueItem.isWebhook ?? false,
|
|
62
121
|
},
|
|
63
122
|
};
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
123
|
+
try {
|
|
124
|
+
await world.events.create(runId, hookDisposedEvent, { requestId });
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
if (EntityConflictError.is(err)) {
|
|
128
|
+
// Hook was already disposed by a concurrent invocation — safe to skip
|
|
129
|
+
runtimeLogger.info('Hook already disposed, skipping duplicate disposal', {
|
|
130
|
+
workflowRunId: runId,
|
|
131
|
+
correlationId: queueItem.correlationId,
|
|
132
|
+
message: err.message,
|
|
74
133
|
});
|
|
75
|
-
// Check if the world returned a hook_conflict event instead of hook_created
|
|
76
|
-
// The hook_conflict event is stored in the event log and will be replayed
|
|
77
|
-
// on the next workflow invocation, causing the hook's promise to reject
|
|
78
|
-
// Note: hook events always create an event (legacy runs throw, not return undefined)
|
|
79
|
-
if (result.event.eventType === 'hook_conflict') {
|
|
80
|
-
hasHookConflict = true;
|
|
81
|
-
}
|
|
82
134
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
135
|
+
else if (RunExpiredError.is(err)) {
|
|
136
|
+
runtimeLogger.info('Workflow run already completed, skipping hook disposal', {
|
|
137
|
+
workflowRunId: runId,
|
|
138
|
+
correlationId: queueItem.correlationId,
|
|
139
|
+
message: err.message,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
else if (HookNotFoundError.is(err)) {
|
|
143
|
+
// Hook may have already been disposed or never created
|
|
144
|
+
runtimeLogger.info('Hook not found for disposal, continuing', {
|
|
145
|
+
workflowRunId: runId,
|
|
146
|
+
correlationId: queueItem.correlationId,
|
|
147
|
+
message: err.message,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
throw err;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// Process hooks first to prevent race conditions with webhook receivers.
|
|
156
|
+
// Track any hook conflicts that occur — these are returned to the caller
|
|
157
|
+
// so the V2 handler can re-invoke immediately.
|
|
158
|
+
let hasHookConflict = false;
|
|
159
|
+
let hasAwaitedHookCreation = false;
|
|
160
|
+
let hookCreationMs = 0;
|
|
161
|
+
if (hookItemsByToken.size > 0) {
|
|
162
|
+
const hookPhaseStart = Date.now();
|
|
163
|
+
await ensureRunReady();
|
|
164
|
+
await Promise.all([...hookItemsByToken.values()].map(async (items) => {
|
|
165
|
+
for (const queueItem of items) {
|
|
166
|
+
let creationConflicted = false;
|
|
167
|
+
if (!queueItem.hasCreatedEvent) {
|
|
168
|
+
const hookMetadata = typeof queueItem.metadata === 'undefined'
|
|
169
|
+
? undefined
|
|
170
|
+
: (await dehydrateStepArguments(queueItem.metadata, runId, encryptionKey, suspension.globalThis, false, compression));
|
|
171
|
+
const hookEvent = {
|
|
172
|
+
eventType: 'hook_created',
|
|
173
|
+
specVersion: SPEC_VERSION_CURRENT,
|
|
174
|
+
correlationId: queueItem.correlationId,
|
|
175
|
+
eventData: {
|
|
176
|
+
token: queueItem.token,
|
|
177
|
+
metadata: hookMetadata,
|
|
178
|
+
isWebhook: queueItem.isWebhook ?? false,
|
|
179
|
+
...(queueItem.isSystem && { isSystem: true }),
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
const result = await createHookEvent({
|
|
183
|
+
world,
|
|
184
|
+
runId,
|
|
185
|
+
hookEvent,
|
|
186
|
+
queueItem,
|
|
187
|
+
requestId,
|
|
88
188
|
});
|
|
189
|
+
hasHookConflict ||= result.hasHookConflict;
|
|
190
|
+
hasAwaitedHookCreation ||= result.hasAwaitedHookCreation;
|
|
191
|
+
creationConflicted = result.hasHookConflict;
|
|
89
192
|
}
|
|
90
|
-
|
|
91
|
-
|
|
193
|
+
// Dispose after creation for hooks born and disposed within this
|
|
194
|
+
// batch. A hook whose creation conflicted was never created, so
|
|
195
|
+
// there is nothing to dispose.
|
|
196
|
+
if (queueItem.disposed && !creationConflicted) {
|
|
197
|
+
await disposeHook(queueItem);
|
|
92
198
|
}
|
|
93
199
|
}
|
|
94
200
|
}));
|
|
201
|
+
hookCreationMs = Date.now() - hookPhaseStart;
|
|
95
202
|
}
|
|
96
|
-
// Process
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
specVersion: SPEC_VERSION_CURRENT,
|
|
102
|
-
correlationId: queueItem.correlationId,
|
|
103
|
-
};
|
|
203
|
+
// Process abort requests — resume the hook with abort payload and write stream packet
|
|
204
|
+
const hooksNeedingAbort = allHookItems.filter((item) => item.abortRequested && !item.disposed);
|
|
205
|
+
if (hooksNeedingAbort.length > 0) {
|
|
206
|
+
await ensureRunReady();
|
|
207
|
+
await Promise.all(hooksNeedingAbort.map(async (queueItem) => {
|
|
104
208
|
try {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
209
|
+
// Dehydrate the abort payload for storage
|
|
210
|
+
const abortPayload = await dehydrateStepArguments({ aborted: true, reason: queueItem.abortReason }, runId, encryptionKey, suspension.globalThis, false, compression);
|
|
211
|
+
// Create hook_received event with abort payload
|
|
212
|
+
await world.events.create(runId, {
|
|
213
|
+
eventType: 'hook_received',
|
|
214
|
+
specVersion: SPEC_VERSION_CURRENT,
|
|
215
|
+
correlationId: queueItem.correlationId,
|
|
216
|
+
eventData: {
|
|
217
|
+
token: queueItem.token,
|
|
218
|
+
payload: abortPayload,
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
// Write stream cancellation packet for real-time step propagation.
|
|
222
|
+
// Reuse the same dehydrated payload as the hook event so the reason
|
|
223
|
+
// round-trips through `dehydrateStepArguments` / `hydrateStepArguments`
|
|
224
|
+
// (handles DOMException, custom errors, encryption, etc.) instead of
|
|
225
|
+
// bare JSON.stringify which loses type information and drops undefined.
|
|
226
|
+
// streamName is set on the queue item at controller construction time
|
|
227
|
+
// (see workflow/abort-controller.ts).
|
|
228
|
+
try {
|
|
229
|
+
const streamName = getAbortStreamIdFromToken(queueItem.token);
|
|
230
|
+
await world.streams.write(runId, streamName, abortPayload);
|
|
231
|
+
await world.streams.close(runId, streamName);
|
|
115
232
|
}
|
|
116
|
-
|
|
117
|
-
|
|
233
|
+
catch {
|
|
234
|
+
// Best-effort stream write — hook event provides the durable fallback
|
|
235
|
+
runtimeLogger.debug('Failed to write abort stream packet, hook event will provide fallback', {
|
|
118
236
|
workflowRunId: runId,
|
|
119
237
|
correlationId: queueItem.correlationId,
|
|
120
|
-
message: err.message,
|
|
121
238
|
});
|
|
122
239
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
240
|
+
}
|
|
241
|
+
catch (err) {
|
|
242
|
+
if (EntityConflictError.is(err) || RunExpiredError.is(err)) {
|
|
243
|
+
runtimeLogger.info('Workflow run already completed, skipping abort', {
|
|
126
244
|
workflowRunId: runId,
|
|
127
245
|
correlationId: queueItem.correlationId,
|
|
128
246
|
message: err.message,
|
|
@@ -134,35 +252,76 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
134
252
|
}
|
|
135
253
|
}));
|
|
136
254
|
}
|
|
137
|
-
//
|
|
255
|
+
// Create step events for steps that don't have them yet.
|
|
256
|
+
// Unlike V1, we do NOT queue step messages from here — the caller
|
|
257
|
+
// decides which steps to execute inline vs. queue to background.
|
|
258
|
+
// Wait events are also created in parallel below.
|
|
138
259
|
const stepsNeedingCreation = new Set(stepItems
|
|
139
260
|
.filter((queueItem) => !queueItem.hasCreatedEvent)
|
|
140
261
|
.map((queueItem) => queueItem.correlationId));
|
|
141
|
-
//
|
|
142
|
-
//
|
|
143
|
-
//
|
|
262
|
+
// Correlation IDs for which THIS suspension call actually wrote the
|
|
263
|
+
// step_created event. Populated by the ops below after a successful
|
|
264
|
+
// events.create — used by the caller to claim ownership and avoid
|
|
265
|
+
// racing with concurrent handlers on step execution.
|
|
266
|
+
const createdStepCorrelationIds = new Set();
|
|
267
|
+
// Lazy inline start: defer the step_created write for up to
|
|
268
|
+
// `getMaxInlineSteps()` steps the caller will run inline (in parallel). Each
|
|
269
|
+
// step is created on the fly by the lazy `step_started` executeStep sends
|
|
270
|
+
// (saving a round-trip per step). We never defer when a `hook.getConflict()`
|
|
271
|
+
// awaiter is present, because in that case the caller executes nothing inline
|
|
272
|
+
// (it re-invokes immediately to resolve the awaiter), so deferring would
|
|
273
|
+
// leave the steps uncreated and unqueued. We pick the first N uncreated steps
|
|
274
|
+
// — matching the caller's inline-candidate selection — and dehydrate their
|
|
275
|
+
// input here so executeStep can ship it as the step_started payload.
|
|
276
|
+
const lazyInlineCorrelationIds = new Set(hasAwaitedHookCreation === false
|
|
277
|
+
? stepItems
|
|
278
|
+
.filter((item) => stepsNeedingCreation.has(item.correlationId))
|
|
279
|
+
.slice(0, getMaxInlineSteps())
|
|
280
|
+
.map((item) => item.correlationId)
|
|
281
|
+
: []);
|
|
282
|
+
// Collected by correlationId because the per-step ops below run concurrently
|
|
283
|
+
// and settle out of order. We rebuild the array in deterministic
|
|
284
|
+
// `lazyInlineCorrelationIds` order (the ordered slice above) after the ops
|
|
285
|
+
// settle, so the inline batch order is stable regardless of dehydration timing.
|
|
286
|
+
const lazyInlineByCorrelationId = new Map();
|
|
144
287
|
const ops = [];
|
|
145
|
-
// Steps: create
|
|
288
|
+
// Steps: create step_created events (no queuing — V2 returns pending steps to caller)
|
|
146
289
|
for (const queueItem of stepItems) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
if (stepsNeedingCreation.has(queueItem.correlationId)) {
|
|
290
|
+
if (stepsNeedingCreation.has(queueItem.correlationId)) {
|
|
291
|
+
ops.push((async () => {
|
|
150
292
|
const dehydratedInput = await dehydrateStepArguments({
|
|
151
293
|
args: queueItem.args,
|
|
152
294
|
closureVars: queueItem.closureVars,
|
|
153
295
|
thisVal: queueItem.thisVal,
|
|
154
|
-
}, runId, encryptionKey, suspension.globalThis);
|
|
296
|
+
}, runId, encryptionKey, suspension.globalThis, false, compression);
|
|
297
|
+
// Deferred (lazy) inline step: skip the step_created write — the
|
|
298
|
+
// caller's inline executeStep will send a lazy step_started carrying
|
|
299
|
+
// this input, and the world creates the step (entity + synthetic
|
|
300
|
+
// step_created event) atomically. We do NOT add it to
|
|
301
|
+
// createdStepCorrelationIds; ownership is decided by that lazy
|
|
302
|
+
// step_started's atomic create-claim instead.
|
|
303
|
+
if (lazyInlineCorrelationIds.has(queueItem.correlationId)) {
|
|
304
|
+
lazyInlineByCorrelationId.set(queueItem.correlationId, {
|
|
305
|
+
correlationId: queueItem.correlationId,
|
|
306
|
+
stepName: queueItem.stepName,
|
|
307
|
+
dehydratedInput: dehydratedInput,
|
|
308
|
+
});
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
155
311
|
const stepEvent = {
|
|
156
312
|
eventType: 'step_created',
|
|
157
313
|
specVersion: SPEC_VERSION_CURRENT,
|
|
158
314
|
correlationId: queueItem.correlationId,
|
|
159
315
|
eventData: {
|
|
160
316
|
stepName: queueItem.stepName,
|
|
317
|
+
workflowName: run.workflowName,
|
|
161
318
|
input: dehydratedInput,
|
|
162
319
|
},
|
|
163
320
|
};
|
|
164
321
|
try {
|
|
322
|
+
await ensureRunReady();
|
|
165
323
|
await world.events.create(runId, stepEvent, { requestId });
|
|
324
|
+
createdStepCorrelationIds.add(queueItem.correlationId);
|
|
166
325
|
}
|
|
167
326
|
catch (err) {
|
|
168
327
|
if (EntityConflictError.is(err)) {
|
|
@@ -176,28 +335,10 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
176
335
|
throw err;
|
|
177
336
|
}
|
|
178
337
|
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
// Serialize trace context once and include in both payload and headers
|
|
182
|
-
// Payload: for manual context restoration in step handler
|
|
183
|
-
// Headers: for automatic trace propagation by Vercel's infrastructure
|
|
184
|
-
const traceCarrier = await serializeTraceCarrier();
|
|
185
|
-
await queueMessage(world, `__wkf_step_${queueItem.stepName}`, {
|
|
186
|
-
workflowName,
|
|
187
|
-
workflowRunId: runId,
|
|
188
|
-
workflowStartedAt,
|
|
189
|
-
stepId: queueItem.correlationId,
|
|
190
|
-
traceCarrier,
|
|
191
|
-
requestedAt: new Date(),
|
|
192
|
-
}, {
|
|
193
|
-
idempotencyKey: queueItem.correlationId,
|
|
194
|
-
headers: {
|
|
195
|
-
...extractTraceHeaders(traceCarrier),
|
|
196
|
-
},
|
|
197
|
-
});
|
|
198
|
-
})());
|
|
338
|
+
})());
|
|
339
|
+
}
|
|
199
340
|
}
|
|
200
|
-
//
|
|
341
|
+
// Create wait events (same as V1)
|
|
201
342
|
for (const queueItem of waitItems) {
|
|
202
343
|
if (!queueItem.hasCreatedEvent) {
|
|
203
344
|
ops.push((async () => {
|
|
@@ -210,6 +351,7 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
210
351
|
},
|
|
211
352
|
};
|
|
212
353
|
try {
|
|
354
|
+
await ensureRunReady();
|
|
213
355
|
await world.events.create(runId, waitEvent, { requestId });
|
|
214
356
|
}
|
|
215
357
|
catch (err) {
|
|
@@ -227,40 +369,116 @@ export async function handleSuspension({ suspension, world, run, span, requestId
|
|
|
227
369
|
})());
|
|
228
370
|
}
|
|
229
371
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
372
|
+
for (const queueItem of attributeItems) {
|
|
373
|
+
ops.push((async () => {
|
|
374
|
+
try {
|
|
375
|
+
await ensureRunReady();
|
|
376
|
+
await world.events.create(runId, {
|
|
377
|
+
eventType: 'attr_set',
|
|
378
|
+
specVersion: SPEC_VERSION_CURRENT,
|
|
379
|
+
correlationId: queueItem.correlationId,
|
|
380
|
+
eventData: {
|
|
381
|
+
changes: queueItem.changes,
|
|
382
|
+
writer: { type: 'workflow' },
|
|
383
|
+
...(queueItem.allowReservedAttributes
|
|
384
|
+
? { allowReservedAttributes: true }
|
|
385
|
+
: {}),
|
|
386
|
+
},
|
|
387
|
+
}, { requestId });
|
|
388
|
+
}
|
|
389
|
+
catch (err) {
|
|
390
|
+
if (EntityConflictError.is(err)) {
|
|
391
|
+
runtimeLogger.info('Workflow attribute event already exists, continuing', {
|
|
392
|
+
workflowRunId: runId,
|
|
393
|
+
correlationId: queueItem.correlationId,
|
|
394
|
+
message: err.message,
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
else if (isAttributeValidationFailure(err)) {
|
|
398
|
+
// Deterministic validation rejection from the World — e.g. the
|
|
399
|
+
// cumulative per-run attribute cap, which only the World can
|
|
400
|
+
// check against the run's existing attributes. Redelivering the
|
|
401
|
+
// orchestrator message replays the workflow into the exact same
|
|
402
|
+
// write and the exact same rejection, so retrying can never
|
|
403
|
+
// succeed. Surface it as a FatalError so the caller fails the
|
|
404
|
+
// run with a clear error instead of wedging it in redelivery.
|
|
405
|
+
const fatal = new FatalError(`setAttributes failed World validation: ${err instanceof Error ? err.message : String(err)}`);
|
|
406
|
+
fatal.cause = err;
|
|
407
|
+
throw fatal;
|
|
408
|
+
}
|
|
409
|
+
else {
|
|
410
|
+
throw err;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
})());
|
|
414
|
+
}
|
|
415
|
+
// Await the step_created / wait_created event creates before returning.
|
|
416
|
+
// The caller (workflowEntrypoint) only enqueues the step-dispatch queue
|
|
417
|
+
// messages AFTER handleSuspension resolves, and the queue handler acks
|
|
418
|
+
// the orchestrator message only after the caller resolves. So the step_created
|
|
419
|
+
// events must be durable here, and the dispatch sends must complete in the caller,
|
|
420
|
+
// all before ack. If the process crashes before this resolves, the orchestrator
|
|
421
|
+
// message is not acked and VQS redelivers, re-creates the (idempotent)
|
|
422
|
+
// step_created and re-dispatches, and recovers the run instead of orphaning it.
|
|
236
423
|
await Promise.all(ops);
|
|
237
|
-
//
|
|
424
|
+
// Rebuild the inline batch in deterministic order. `lazyInlineCorrelationIds`
|
|
425
|
+
// is a Set seeded from the ordered first-N slice, so iterating it preserves
|
|
426
|
+
// stepItems order; every id in it was set by the lazy branch above.
|
|
427
|
+
const lazyInlineSteps = [];
|
|
428
|
+
for (const correlationId of lazyInlineCorrelationIds) {
|
|
429
|
+
const lazyStep = lazyInlineByCorrelationId.get(correlationId);
|
|
430
|
+
if (lazyStep)
|
|
431
|
+
lazyInlineSteps.push(lazyStep);
|
|
432
|
+
}
|
|
433
|
+
// Find the soonest pending wait (minimum timeout)
|
|
238
434
|
const now = Date.now();
|
|
239
|
-
|
|
435
|
+
let soonestWait;
|
|
436
|
+
for (const queueItem of waitItems) {
|
|
240
437
|
const resumeAtMs = queueItem.resumeAt.getTime();
|
|
241
438
|
const delayMs = Math.max(1000, resumeAtMs - now);
|
|
242
439
|
const timeoutSeconds = Math.ceil(delayMs / 1000);
|
|
243
|
-
if (
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
440
|
+
if (!soonestWait || timeoutSeconds < soonestWait.seconds) {
|
|
441
|
+
soonestWait = {
|
|
442
|
+
seconds: timeoutSeconds,
|
|
443
|
+
correlationId: queueItem.correlationId,
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
}
|
|
247
447
|
span?.setAttributes({
|
|
248
448
|
...Attribute.WorkflowRunStatus('workflow_suspended'),
|
|
249
449
|
...Attribute.WorkflowStepsCreated(stepItems.length),
|
|
250
450
|
...Attribute.WorkflowHooksCreated(hooksNeedingCreation.length),
|
|
251
451
|
...Attribute.WorkflowWaitsCreated(waitItems.length),
|
|
252
452
|
});
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
453
|
+
return {
|
|
454
|
+
pendingSteps: stepItems,
|
|
455
|
+
createdStepCorrelationIds,
|
|
456
|
+
lazyInlineSteps,
|
|
457
|
+
// On hook conflict the caller re-invokes immediately and never reads
|
|
458
|
+
// the wait timeout, so don't report one.
|
|
459
|
+
waitTimeout: hasHookConflict ? undefined : soonestWait,
|
|
460
|
+
hasHookConflict,
|
|
461
|
+
hasAwaitedHookCreation,
|
|
462
|
+
hasAttributeEvents: attributeItems.length > 0,
|
|
463
|
+
hasHookEvents: hooksNeedingCreation.length > 0,
|
|
464
|
+
hookCreationMs,
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Whether an `events.create` rejection is a deterministic attribute
|
|
469
|
+
* validation failure rather than a transient/storage error. Local Worlds
|
|
470
|
+
* (world-local, world-postgres) throw `AttributeValidationError` directly;
|
|
471
|
+
* remote Worlds surface the equivalent server-side rejection as a
|
|
472
|
+
* `WorkflowWorldError` with HTTP status 400. The name check covers
|
|
473
|
+
* `AttributeValidationError` instances from a different copy of
|
|
474
|
+
* `@workflow/world` than the one this package resolved.
|
|
475
|
+
*/
|
|
476
|
+
function isAttributeValidationFailure(err) {
|
|
477
|
+
if (err instanceof AttributeValidationError)
|
|
478
|
+
return true;
|
|
479
|
+
if (err instanceof Error && err.name === 'AttributeValidationError') {
|
|
480
|
+
return true;
|
|
263
481
|
}
|
|
264
|
-
return
|
|
482
|
+
return WorkflowWorldError.is(err) && err.status === 400;
|
|
265
483
|
}
|
|
266
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3VzcGVuc2lvbi1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bnRpbWUvc3VzcGVuc2lvbi1oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUM5QyxPQUFPLEVBQ0wsbUJBQW1CLEVBQ25CLGlCQUFpQixFQUNqQixlQUFlLEdBQ2hCLE1BQU0sa0JBQWtCLENBQUM7QUFDMUIsT0FBTyxFQUdMLG9CQUFvQixHQUdyQixNQUFNLGlCQUFpQixDQUFDO0FBQ3pCLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQU83QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzdDLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzdELE9BQU8sS0FBSyxTQUFTLE1BQU0sc0NBQXNDLENBQUM7QUFDbEUsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDeEQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUU1Qzs7O0dBR0c7QUFDSCxTQUFTLG1CQUFtQixDQUMxQixZQUFvQztJQUVwQyxNQUFNLE9BQU8sR0FBMkIsRUFBRSxDQUFDO0lBQzNDLElBQUksWUFBWSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQzdCLE9BQU8sQ0FBQyxXQUFXLEdBQUcsWUFBWSxDQUFDLFdBQVcsQ0FBQztJQUNqRCxDQUFDO0lBQ0QsSUFBSSxZQUFZLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDNUIsT0FBTyxDQUFDLFVBQVUsR0FBRyxZQUFZLENBQUMsVUFBVSxDQUFDO0lBQy9DLENBQUM7SUFDRCxPQUFPLE9BQU8sQ0FBQztBQUNqQixDQUFDO0FBY0Q7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLGdCQUFnQixDQUFDLEVBQ3JDLFVB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aW1wb3J0IHsgd2FpdFVudGlsIH0gZnJvbSAnQHZlcmNlbC9mdW5jdGlvbnMnO1xuaW1wb3J0IHtcbiAgRW50aXR5Q29uZmxpY3RFcnJvcixcbiAgSG9va05vdEZvdW5kRXJyb3IsXG4gIFJ1bkV4cGlyZWRFcnJvcixcbn0gZnJvbSAnQHdvcmtmbG93L2Vycm9ycyc7XG5pbXBvcnQge1xuICB0eXBlIENyZWF0ZUV2ZW50UmVxdWVzdCxcbiAgdHlwZSBTZXJpYWxpemVkRGF0YSxcbiAgU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gIHR5cGUgV29ya2Zsb3dSdW4sXG4gIHR5cGUgV29ybGQsXG59IGZyb20gJ0B3b3JrZmxvdy93b3JsZCc7XG5pbXBvcnQgeyBpbXBvcnRLZXkgfSBmcm9tICcuLi9lbmNyeXB0aW9uLmpzJztcbmltcG9ydCB0eXBlIHtcbiAgSG9va0ludm9jYXRpb25RdWV1ZUl0ZW0sXG4gIFN0ZXBJbnZvY2F0aW9uUXVldWVJdGVtLFxuICBXYWl0SW52b2NhdGlvblF1ZXVlSXRlbSxcbiAgV29ya2Zsb3dTdXNwZW5zaW9uLFxufSBmcm9tICcuLi9nbG9iYWwuanMnO1xuaW1wb3J0IHsgcnVudGltZUxvZ2dlciB9IGZyb20gJy4uL2xvZ2dlci5qcyc7XG5pbXBvcnQgeyBkZWh5ZHJhdGVTdGVwQXJndW1lbnRzIH0gZnJvbSAnLi4vc2VyaWFsaXphdGlvbi5qcyc7XG5pbXBvcnQgKiBhcyBBdHRyaWJ1dGUgZnJvbSAnLi4vdGVsZW1ldHJ5L3NlbWFudGljLWNvbnZlbnRpb25zLmpzJztcbmltcG9ydCB7IHNlcmlhbGl6ZVRyYWNlQ2FycmllciB9IGZyb20gJy4uL3RlbGVtZXRyeS5qcyc7XG5pbXBvcnQgeyBxdWV1ZU1lc3NhZ2UgfSBmcm9tICcuL2hlbHBlcnMuanMnO1xuXG4vKipcbiAqIEV4dHJhY3RzIFczQyB0cmFjZSBjb250ZXh0IGhlYWRlcnMgZnJvbSBhIHRyYWNlIGNhcnJpZXIgZm9yIEhUVFAgcHJvcGFnYXRpb24uXG4gKiBSZXR1cm5zIGFuIG9iamVjdCB3aXRoIGB0cmFjZXBhcmVudGAgYW5kIG9wdGlvbmFsbHkgYHRyYWNlc3RhdGVgIGhlYWRlcnMuXG4gKi9cbmZ1bmN0aW9uIGV4dHJhY3RUcmFjZUhlYWRlcnMoXG4gIHRyYWNlQ2FycmllcjogUmVjb3JkPHN0cmluZywgc3RyaW5nPlxuKTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB7XG4gIGNvbnN0IGhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgaWYgKHRyYWNlQ2Fycmllci50cmFjZXBhcmVudCkge1xuICAgIGhlYWRlcnMudHJhY2VwYXJlbnQgPSB0cmFjZUNhcnJpZXIudHJhY2VwYXJlbnQ7XG4gIH1cbiAgaWYgKHRyYWNlQ2Fycmllci50cmFjZXN0YXRlKSB7XG4gICAgaGVhZGVycy50cmFjZXN0YXRlID0gdHJhY2VDYXJyaWVyLnRyYWNlc3RhdGU7XG4gIH1cbiAgcmV0dXJuIGhlYWRlcnM7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3VzcGVuc2lvbkhhbmRsZXJQYXJhbXMge1xuICBzdXNwZW5zaW9uOiBXb3JrZmxvd1N1c3BlbnNpb247XG4gIHdvcmxkOiBXb3JsZDtcbiAgcnVuOiBXb3JrZmxvd1J1bjtcbiAgc3Bhbj86IFNwYW47XG4gIHJlcXVlc3RJZD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTdXNwZW5zaW9uSGFuZGxlclJlc3VsdCB7XG4gIHRpbWVvdXRTZWNvbmRzPzogbnVtYmVyO1xufVxuXG4vKipcbiAqIEhhbmRsZXMgYSB3b3JrZmxvdyBzdXNwZW5zaW9uIGJ5IHByb2Nlc3NpbmcgYWxsIHBlbmRpbmcgb3BlcmF0aW9ucyAoaG9va3MsIHN0ZXBzLCB3YWl0cykuXG4gKiBVc2VzIGFuIGV2ZW50LXNvdXJjZWQgYXJjaGl0ZWN0dXJlIHdoZXJlIGVudGl0aWVzIChzdGVwcywgaG9va3MpIGFyZSBjcmVhdGVkIGF0b21pY2FsbHlcbiAqIHdpdGggdGhlaXIgY29ycmVzcG9uZGluZyBldmVudHMgdmlhIGV2ZW50cy5jcmVhdGUoKS5cbiAqXG4gKiBQcm9jZXNzaW5nIG9yZGVyOlxuICogMS4gSG9va3MgYXJlIHByb2Nlc3NlZCBmaXJzdCB0byBwcmV2ZW50IHJhY2UgY29uZGl0aW9ucyB3aXRoIHdlYmhvb2sgcmVjZWl2ZXJzXG4gKiAyLiBTdGVwcyBhbmQgd2FpdHMgYXJlIHByb2Nlc3NlZCBpbiBwYXJhbGxlbCBhZnRlciBob29rcyBjb21wbGV0ZVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaGFuZGxlU3VzcGVuc2lvbih7XG4gIHN1c3BlbnNpb24sXG4gIHdvcmxkLFxuICBydW4sXG4gIHNwYW4sXG4gIHJlcXVlc3RJZCxcbn06IFN1c3BlbnNpb25IYW5kbGVyUGFyYW1zKTogUHJvbWlzZTxTdXNwZW5zaW9uSGFuZGxlclJlc3VsdD4ge1xuICBjb25zdCBydW5JZCA9IHJ1bi5ydW5JZDtcbiAgY29uc3Qgd29ya2Zsb3dOYW1lID0gcnVuLndvcmtmbG93TmFtZTtcbiAgY29uc3Qgd29ya2Zsb3dTdGFydGVkQXQgPSBydW4uc3RhcnRlZEF0ID8gK3J1bi5zdGFydGVkQXQgOiBEYXRlLm5vdygpO1xuICAvLyBTZXBhcmF0ZSBxdWV1ZSBpdGVtcyBieSB0eXBlXG4gIGNvbnN0IHN0ZXBJdGVtcyA9IHN1c3BlbnNpb24uc3RlcHMuZmlsdGVyKFxuICAgIChpdGVtKTogaXRlbSBpcyBTdGVwSW52b2NhdGlvblF1ZXVlSXRlbSA9PiBpdGVtLnR5cGUgPT09ICdzdGVwJ1xuICApO1xuICBjb25zdCBhbGxIb29rSXRlbXMgPSBzdXNwZW5zaW9uLnN0ZXBzLmZpbHRlcihcbiAgICAoaXRlbSk6IGl0ZW0gaXMgSG9va0ludm9jYXRpb25RdWV1ZUl0ZW0gPT4gaXRlbS50eXBlID09PSAnaG9vaydcbiAgKTtcbiAgY29uc3Qgd2FpdEl0ZW1zID0gc3VzcGVuc2lvbi5zdGVwcy5maWx0ZXIoXG4gICAgKGl0ZW0pOiBpdGVtIGlzIFdhaXRJbnZvY2F0aW9uUXVldWVJdGVtID0+IGl0ZW0udHlwZSA9PT0gJ3dhaXQnXG4gICk7XG5cbiAgLy8gU3BsaXQgaG9va3MgYnkgd2hhdCBhY3Rpb25zIHRoZXkgbmVlZFxuICBjb25zdCBob29rc05lZWRpbmdDcmVhdGlvbiA9IGFsbEhvb2tJdGVtcy5maWx0ZXIoXG4gICAgKGl0ZW0pID0+ICFpdGVtLmhhc0NyZWF0ZWRFdmVudFxuICApO1xuICAvLyBIb29rcyBuZWVkaW5nIGRpc3Bvc2FsOiBhbnkgZGlzcG9zZWQgaG9vayAoaW5jbHVkaW5nIHRob3NlIG5lZWRpbmcgY3JlYXRpb24gZmlyc3QpXG4gIC8vIEhvb2tzIGFyZSBjcmVhdGVkIGJlZm9yZSBkaXNwb3NhbCBpbiB0aGUgcHJvY2Vzc2luZyBvcmRlciBiZWxvd1xuICBjb25zdCBob29rc05lZWRpbmdEaXNwb3NhbCA9IGFsbEhvb2tJdGVtcy5maWx0ZXIoKGl0ZW0pID0+IGl0ZW0uZGlzcG9zZWQpO1xuXG4gIC8vIFJlc29sdmUgZW5jcnlwdGlvbiBrZXkgZm9yIHRoaXMgcnVuXG4gIGNvbnN0IHJhd0tleSA9IGF3YWl0IHdvcmxkLmdldEVuY3J5cHRpb25LZXlGb3JSdW4/LihydW4pO1xuICBjb25zdCBlbmNyeXB0aW9uS2V5ID0gcmF3S2V5ID8gYXdhaXQgaW1wb3J0S2V5KHJhd0tleSkgOiB1bmRlZmluZWQ7XG5cbiAgLy8gQnVpbGQgaG9va19jcmVhdGVkIGV2ZW50cyAoV29ybGQgd2lsbCBhdG9taWNhbGx5IGNyZWF0ZSBob29rIGVudGl0aWVzKVxuICBjb25zdCBob29rRXZlbnRzOiBDcmVhdGVFdmVudFJlcXVlc3RbXSA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgIGhvb2tzTmVlZGluZ0NyZWF0aW9uLm1hcChhc3luYyAocXVldWVJdGVtKSA9PiB7XG4gICAgICBjb25zdCBob29rTWV0YWRhdGE6IFNlcmlhbGl6ZWREYXRhIHwgdW5kZWZpbmVkID1cbiAgICAgICAgdHlwZW9mIHF1ZXVlSXRlbS5tZXRhZGF0YSA9PT0gJ3VuZGVmaW5lZCdcbiAgICAgICAgICA/IHVuZGVmaW5lZFxuICAgICAgICAgIDogKChhd2FpdCBkZWh5ZHJhdGVTdGVwQXJndW1lbnRzKFxuICAgICAgICAgICAgICBxdWV1ZUl0ZW0ubWV0YWRhdGEsXG4gICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICBlbmNyeXB0aW9uS2V5LFxuICAgICAgICAgICAgICBzdXNwZW5zaW9uLmdsb2JhbFRoaXNcbiAgICAgICAgICAgICkpIGFzIFNlcmlhbGl6ZWREYXRhKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGV2ZW50VHlwZTogJ2hvb2tfY3JlYXRlZCcgYXMgY29uc3QsXG4gICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgIHRva2VuOiBxdWV1ZUl0ZW0udG9rZW4sXG4gICAgICAgICAgbWV0YWRhdGE6IGhvb2tNZXRhZGF0YSxcbiAgICAgICAgICBpc1dlYmhvb2s6IHF1ZXVlSXRlbS5pc1dlYmhvb2sgPz8gZmFsc2UsXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH0pXG4gICk7XG5cbiAgLy8gUHJvY2VzcyBob29rcyBmaXJzdCB0byBwcmV2ZW50IHJhY2UgY29uZGl0aW9ucyB3aXRoIHdlYmhvb2sgcmVjZWl2ZXJzXG4gIC8vIEFsbCBob29rIGNyZWF0aW9ucyBydW4gaW4gcGFyYWxsZWxcbiAgLy8gVHJhY2sgYW55IGhvb2sgY29uZmxpY3RzIHRoYXQgb2NjdXIgLSB0aGVzZSB3aWxsIGJlIGhhbmRsZWQgYnkgcmUtZW5xdWV1ZWluZyB0aGUgd29ya2Zsb3dcbiAgbGV0IGhhc0hvb2tDb25mbGljdCA9IGZhbHNlO1xuXG4gIGlmIChob29rRXZlbnRzLmxlbmd0aCA+IDApIHtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIGhvb2tFdmVudHMubWFwKGFzeW5jIChob29rRXZlbnQpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKHJ1bklkLCBob29rRXZlbnQsIHtcbiAgICAgICAgICAgIHJlcXVlc3RJZCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICAvLyBDaGVjayBpZiB0aGUgd29ybGQgcmV0dXJuZWQgYSBob29rX2NvbmZsaWN0IGV2ZW50IGluc3RlYWQgb2YgaG9va19jcmVhdGVkXG4gICAgICAgICAgLy8gVGhlIGhvb2tfY29uZmxpY3QgZXZlbnQgaXMgc3RvcmVkIGluIHRoZSBldmVudCBsb2cgYW5kIHdpbGwgYmUgcmVwbGF5ZWRcbiAgICAgICAgICAvLyBvbiB0aGUgbmV4dCB3b3JrZmxvdyBpbnZvY2F0aW9uLCBjYXVzaW5nIHRoZSBob29rJ3MgcHJvbWlzZSB0byByZWplY3RcbiAgICAgICAgICAvLyBOb3RlOiBob29rIGV2ZW50cyBhbHdheXMgY3JlYXRlIGFuIGV2ZW50IChsZWdhY3kgcnVucyB0aHJvdywgbm90IHJldHVybiB1bmRlZmluZWQpXG4gICAgICAgICAgaWYgKHJlc3VsdC5ldmVudCEuZXZlbnRUeXBlID09PSAnaG9va19jb25mbGljdCcpIHtcbiAgICAgICAgICAgIGhhc0hvb2tDb25mbGljdCA9IHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpIHx8IFJ1bkV4cGlyZWRFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICdXb3JrZmxvdyBydW4gYWxyZWFkeSBjb21wbGV0ZWQsIHNraXBwaW5nIGhvb2snLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIC8vIFByb2Nlc3MgaG9vayBkaXNwb3NhbHMgLSB0aGVzZSByZWxlYXNlIGhvb2sgdG9rZW5zIGZvciByZXVzZSBieSBvdGhlciB3b3JrZmxvd3NcbiAgaWYgKGhvb2tzTmVlZGluZ0Rpc3Bvc2FsLmxlbmd0aCA+IDApIHtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIGhvb2tzTmVlZGluZ0Rpc3Bvc2FsLm1hcChhc3luYyAocXVldWVJdGVtKSA9PiB7XG4gICAgICAgIGNvbnN0IGhvb2tEaXNwb3NlZEV2ZW50OiBDcmVhdGVFdmVudFJlcXVlc3QgPSB7XG4gICAgICAgICAgZXZlbnRUeXBlOiAnaG9va19kaXNwb3NlZCcgYXMgY29uc3QsXG4gICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICB9O1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUocnVuSWQsIGhvb2tEaXNwb3NlZEV2ZW50LCB7IHJlcXVlc3RJZCB9KTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgLy8gSG9vayB3YXMgYWxyZWFkeSBkaXNwb3NlZCBieSBhIGNvbmN1cnJlbnQgaW52b2NhdGlvbiDigJQgc2FmZSB0byBza2lwXG4gICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICdIb29rIGFscmVhZHkgZGlzcG9zZWQsIHNraXBwaW5nIGR1cGxpY2F0ZSBkaXNwb3NhbCcsXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKFJ1bkV4cGlyZWRFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICdXb3JrZmxvdyBydW4gYWxyZWFkeSBjb21wbGV0ZWQsIHNraXBwaW5nIGhvb2sgZGlzcG9zYWwnLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIGlmIChIb29rTm90Rm91bmRFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAvLyBIb29rIG1heSBoYXZlIGFscmVhZHkgYmVlbiBkaXNwb3NlZCBvciBuZXZlciBjcmVhdGVkXG4gICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ0hvb2sgbm90IGZvdW5kIGZvciBkaXNwb3NhbCwgY29udGludWluZycsIHtcbiAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvLyBCdWlsZCBhIG1hcCBvZiBzdGVwSWQgLT4gc3RlcCBldmVudCBmb3Igc3RlcHMgdGhhdCBuZWVkIGNyZWF0aW9uXG4gIGNvbnN0IHN0ZXBzTmVlZGluZ0NyZWF0aW9uID0gbmV3IFNldChcbiAgICBzdGVwSXRlbXNcbiAgICAgIC5maWx0ZXIoKHF1ZXVlSXRlbSkgPT4gIXF1ZXVlSXRlbS5oYXNDcmVhdGVkRXZlbnQpXG4gICAgICAubWFwKChxdWV1ZUl0ZW0pID0+IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKVxuICApO1xuXG4gIC8vIFByb2Nlc3Mgc3RlcHMgYW5kIHdhaXRzIGluIHBhcmFsbGVsXG4gIC8vIEVhY2ggc3RlcDogY3JlYXRlIGV2ZW50IChpZiBuZWVkZWQpIC0+IHF1ZXVlIG1lc3NhZ2VcbiAgLy8gRWFjaCB3YWl0OiBjcmVhdGUgZXZlbnQgKGlmIG5lZWRlZClcbiAgY29uc3Qgb3BzOiBQcm9taXNlPHZvaWQ+W10gPSBbXTtcblxuICAvLyBTdGVwczogY3JlYXRlIGV2ZW50IHRoZW4gcXVldWUgbWVzc2FnZSwgYWxsIGluIHBhcmFsbGVsXG4gIGZvciAoY29uc3QgcXVldWVJdGVtIG9mIHN0ZXBJdGVtcykge1xuICAgIG9wcy5wdXNoKFxuICAgICAgKGFzeW5jICgpID0+IHtcbiAgICAgICAgLy8gQ3JlYXRlIHN0ZXAgZXZlbnQgaWYgbm90IGFscmVhZHkgY3JlYXRlZFxuICAgICAgICBpZiAoc3RlcHNOZWVkaW5nQ3JlYXRpb24uaGFzKHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKSkge1xuICAgICAgICAgIGNvbnN0IGRlaHlkcmF0ZWRJbnB1dCA9IGF3YWl0IGRlaHlkcmF0ZVN0ZXBBcmd1bWVudHMoXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGFyZ3M6IHF1ZXVlSXRlbS5hcmdzLFxuICAgICAgICAgICAgICBjbG9zdXJlVmFyczogcXVldWVJdGVtLmNsb3N1cmVWYXJzLFxuICAgICAgICAgICAgICB0aGlzVmFsOiBxdWV1ZUl0ZW0udGhpc1ZhbCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgIGVuY3J5cHRpb25LZXksXG4gICAgICAgICAgICBzdXNwZW5zaW9uLmdsb2JhbFRoaXNcbiAgICAgICAgICApO1xuICAgICAgICAgIGNvbnN0IHN0ZXBFdmVudDogQ3JlYXRlRXZlbnRSZXF1ZXN0ID0ge1xuICAgICAgICAgICAgZXZlbnRUeXBlOiAnc3RlcF9jcmVhdGVkJyBhcyBjb25zdCxcbiAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgIHN0ZXBOYW1lOiBxdWV1ZUl0ZW0uc3RlcE5hbWUsXG4gICAgICAgICAgICAgIGlucHV0OiBkZWh5ZHJhdGVkSW5wdXQgYXMgU2VyaWFsaXplZERhdGEsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH07XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUocnVuSWQsIHN0ZXBFdmVudCwgeyByZXF1ZXN0SWQgfSk7XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbygnU3RlcCBhbHJlYWR5IGV4aXN0cywgY29udGludWluZycsIHtcbiAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gUXVldWUgc3RlcCBleGVjdXRpb24gbWVzc2FnZVxuICAgICAgICAvLyBTZXJpYWxpemUgdHJhY2UgY29udGV4dCBvbmNlIGFuZCBpbmNsdWRlIGluIGJvdGggcGF5bG9hZCBhbmQgaGVhZGVyc1xuICAgICAgICAvLyBQYXlsb2FkOiBmb3IgbWFudWFsIGNvbnRleHQgcmVzdG9yYXRpb24gaW4gc3RlcCBoYW5kbGVyXG4gICAgICAgIC8vIEhlYWRlcnM6IGZvciBhdXRvbWF0aWMgdHJhY2UgcHJvcGFnYXRpb24gYnkgVmVyY2VsJ3MgaW5mcmFzdHJ1Y3R1cmVcbiAgICAgICAgY29uc3QgdHJhY2VDYXJyaWVyID0gYXdhaXQgc2VyaWFsaXplVHJhY2VDYXJyaWVyKCk7XG4gICAgICAgIGF3YWl0IHF1ZXVlTWVzc2FnZShcbiAgICAgICAgICB3b3JsZCxcbiAgICAgICAgICBgX193a2Zfc3RlcF8ke3F1ZXVlSXRlbS5zdGVwTmFtZX1gLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHdvcmtmbG93TmFtZSxcbiAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgd29ya2Zsb3dTdGFydGVkQXQsXG4gICAgICAgICAgICBzdGVwSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgdHJhY2VDYXJyaWVyLFxuICAgICAgICAgICAgcmVxdWVzdGVkQXQ6IG5ldyBEYXRlKCksXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBpZGVtcG90ZW5jeUtleTogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgICAgIC4uLmV4dHJhY3RUcmFjZUhlYWRlcnModHJhY2VDYXJyaWVyKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgfSkoKVxuICAgICk7XG4gIH1cblxuICAvLyBXYWl0czogY3JlYXRlIGV2ZW50cyBpbiBwYXJhbGxlbCAobm8gcXVldWVpbmcgbmVlZGVkIGZvciB3YWl0cylcbiAgZm9yIChjb25zdCBxdWV1ZUl0ZW0gb2Ygd2FpdEl0ZW1zKSB7XG4gICAgaWYgKCFxdWV1ZUl0ZW0uaGFzQ3JlYXRlZEV2ZW50KSB7XG4gICAgICBvcHMucHVzaChcbiAgICAgICAgKGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCB3YWl0RXZlbnQ6IENyZWF0ZUV2ZW50UmVxdWVzdCA9IHtcbiAgICAgICAgICAgIGV2ZW50VHlwZTogJ3dhaXRfY3JlYXRlZCcgYXMgY29uc3QsXG4gICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICByZXN1bWVBdDogcXVldWVJdGVtLnJlc3VtZUF0LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9O1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKHJ1bklkLCB3YWl0RXZlbnQsIHsgcmVxdWVzdElkIH0pO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ1dhaXQgYWxyZWFkeSBleGlzdHMsIGNvbnRpbnVpbmcnLCB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSkoKVxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvLyBXYWl0IGZvciBhbGwgc3RlcCBhbmQgd2FpdCBvcGVyYXRpb25zIHRvIGNvbXBsZXRlXG4gIHdhaXRVbnRpbChcbiAgICBQcm9taXNlLmFsbChvcHMpLmNhdGNoKChvcEVycikgPT4ge1xuICAgICAgY29uc3QgaXNBYm9ydEVycm9yID1cbiAgICAgICAgb3BFcnI/Lm5hbWUgPT09ICdBYm9ydEVycm9yJyB8fCBvcEVycj8ubmFtZSA9PT0gJ1Jlc3BvbnNlQWJvcnRlZCc7XG4gICAgICBpZiAoIWlzQWJvcnRFcnJvcikgdGhyb3cgb3BFcnI7XG4gICAgfSlcbiAgKTtcbiAgYXdhaXQgUHJvbWlzZS5hbGwob3BzKTtcblxuICAvLyBDYWxjdWxhdGUgbWluaW11bSB0aW1lb3V0IGZyb20gd2FpdHNcbiAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgY29uc3QgbWluVGltZW91dFNlY29uZHMgPSB3YWl0SXRlbXMucmVkdWNlPG51bWJlciB8IG51bGw+KFxuICAgIChtaW4sIHF1ZXVlSXRlbSkgPT4ge1xuICAgICAgY29uc3QgcmVzdW1lQXRNcyA9IHF1ZXVlSXRlbS5yZXN1bWVBdC5nZXRUaW1lKCk7XG4gICAgICBjb25zdCBkZWxheU1zID0gTWF0aC5tYXgoMTAwMCwgcmVzdW1lQXRNcyAtIG5vdyk7XG4gICAgICBjb25zdCB0aW1lb3V0U2Vjb25kcyA9IE1hdGguY2VpbChkZWxheU1zIC8gMTAwMCk7XG4gICAgICBpZiAobWluID09PSBudWxsKSByZXR1cm4gdGltZW91dFNlY29uZHM7XG4gICAgICByZXR1cm4gTWF0aC5taW4obWluLCB0aW1lb3V0U2Vjb25kcyk7XG4gICAgfSxcbiAgICBudWxsXG4gICk7XG5cbiAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgLi4uQXR0cmlidXRlLldvcmtmbG93UnVuU3RhdHVzKCd3b3JrZmxvd19zdXNwZW5kZWQnKSxcbiAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dTdGVwc0NyZWF0ZWQoc3RlcEl0ZW1zLmxlbmd0aCksXG4gICAgLi4uQXR0cmlidXRlLldvcmtmbG93SG9va3NDcmVhdGVkKGhvb2tzTmVlZGluZ0NyZWF0aW9uLmxlbmd0aCksXG4gICAgLi4uQXR0cmlidXRlLldvcmtmbG93V2FpdHNDcmVhdGVkKHdhaXRJdGVtcy5sZW5ndGgpLFxuICB9KTtcblxuICAvLyBJZiBhbnkgaG9vayBjb25mbGljdHMgb2NjdXJyZWQsIHJlLWVucXVldWUgdGhlIHdvcmtmbG93IGltbWVkaWF0ZWx5XG4gIC8vIE9uIHRoZSBuZXh0IGl0ZXJhdGlvbiwgdGhlIGhvb2sgY29uc3VtZXIgd2lsbCBzZWUgdGhlIGhvb2tfY29uZmxpY3QgZXZlbnRcbiAgLy8gYW5kIHJlamVjdCB0aGUgcHJvbWlzZSB3aXRoIGEgV29ya2Zsb3dSdW50aW1lRXJyb3JcbiAgLy8gV2UgZG8gdGhpcyBhZnRlciBwcm9jZXNzaW5nIGFsbCBvdGhlciBvcGVyYXRpb25zIChzdGVwcywgd2FpdHMpIHRvIGVuc3VyZVxuICAvLyB0aGV5IGFyZSByZWNvcmRlZCBpbiB0aGUgZXZlbnQgbG9nIGJlZm9yZSB0aGUgcmUtZXhlY3V0aW9uXG4gIGlmIChoYXNIb29rQ29uZmxpY3QpIHtcbiAgICByZXR1cm4geyB0aW1lb3V0U2Vjb25kczogMCB9O1xuICB9XG5cbiAgaWYgKG1pblRpbWVvdXRTZWNvbmRzICE9PSBudWxsKSB7XG4gICAgcmV0dXJuIHsgdGltZW91dFNlY29uZHM6IG1pblRpbWVvdXRTZWNvbmRzIH07XG4gIH1cblxuICByZXR1cm4ge307XG59XG4iXX0=
|
|
484
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3VzcGVuc2lvbi1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bnRpbWUvc3VzcGVuc2lvbi1oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFDTCxtQkFBbUIsRUFDbkIsVUFBVSxFQUNWLGlCQUFpQixFQUNqQixlQUFlLEVBQ2Ysa0JBQWtCLEdBQ25CLE1BQU0sa0JBQWtCLENBQUM7QUFDMUIsT0FBTyxFQUNMLHdCQUF3QixFQUd4QixvQkFBb0IsRUFDcEIsaUNBQWlDLEdBR2xDLE1BQU0saUJBQWlCLENBQUM7QUFDekIsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBUTdDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDN0MsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDN0QsT0FBTyxLQUFLLFNBQVMsTUFBTSxzQ0FBc0MsQ0FBQztBQUNsRSxPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDdkQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFxRm5ELEtBQUssVUFBVSxlQUFlLENBQUMsRUFDN0IsS0FBSyxFQUNMLEtBQUssRUFDTCxTQUFTLEVBQ1QsU0FBUyxFQUNULFNBQVMsR0FPVjtJQUlDLElBQUksQ0FBQztRQUNILE1BQU0sTUFBTSxHQUFHLE1BQU0sS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLFNBQVMsRUFBRTtZQUN6RCxTQUFTO1NBQ1YsQ0FBQyxDQUFDO1FBRUgsNkVBQTZFO1FBQzdFLDBFQUEwRTtRQUMxRSx5RUFBeUU7UUFDekUsSUFBSSxNQUFNLENBQUMsS0FBSyxFQUFFLFNBQVMsS0FBSyxlQUFlLEVBQUUsQ0FBQztZQUNoRCxPQUFPO2dCQUNMLGVBQWUsRUFBRSxJQUFJO2dCQUNyQixzQkFBc0IsRUFBRSxL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LEVBQUUsYUFBYSxDQUFDO1FBQ2xCLEdBQUcsU0FBUyxDQUFDLGlCQUFpQixDQUFDLG9CQUFvQixDQUFDO1FBQ3BELEdBQUcsU0FBUyxDQUFDLG9CQUFvQixDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUM7UUFDbkQsR0FBRyxTQUFTLENBQUMsb0JBQW9CLENBQUMsb0JBQW9CLENBQUMsTUFBTSxDQUFDO1FBQzlELEdBQUcsU0FBUyxDQUFDLG9CQUFvQixDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUM7S0FDcEQsQ0FBQyxDQUFDO0lBRUgsT0FBTztRQUNMLFlBQVksRUFBRSxTQUFTO1FBQ3ZCLHlCQUF5QjtRQUN6QixlQUFlO1FBQ2YscUVBQXFFO1FBQ3JFLHlDQUF5QztRQUN6QyxXQUFXLEVBQUUsZUFBZSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLFdBQVc7UUFDdEQsZUFBZTtRQUNmLHNCQUFzQjtRQUN0QixrQkFBa0IsRUFBRSxjQUFjLENBQUMsTUFBTSxHQUFHLENBQUM7UUFDN0MsYUFBYSxFQUFFLG9CQUFvQixDQUFDLE1BQU0sR0FBRyxDQUFDO1FBQzlDLGNBQWM7S0FDZixDQUFDO0FBQ0osQ0FBQztBQUVEOzs7Ozs7OztHQVFHO0FBQ0gsU0FBUyw0QkFBNEIsQ0FBQyxHQUFZO0lBQ2hELElBQUksR0FBRyxZQUFZLHdCQUF3QjtRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQ3pELElBQUksR0FBRyxZQUFZLEtBQUssSUFBSSxHQUFHLENBQUMsSUFBSSxLQUFLLDBCQUEwQixFQUFFLENBQUM7UUFDcEUsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBQ0QsT0FBTyxrQkFBa0IsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksR0FBRyxDQUFDLE1BQU0sS0FBSyxHQUFHLENBQUM7QUFDMUQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgU3BhbiB9IGZyb20gJ0BvcGVudGVsZW1ldHJ5L2FwaSc7XG5pbXBvcnQge1xuICBFbnRpdHlDb25mbGljdEVycm9yLFxuICBGYXRhbEVycm9yLFxuICBIb29rTm90Rm91bmRFcnJvcixcbiAgUnVuRXhwaXJlZEVycm9yLFxuICBXb3JrZmxvd1dvcmxkRXJyb3IsXG59IGZyb20gJ0B3b3JrZmxvdy9lcnJvcnMnO1xuaW1wb3J0IHtcbiAgQXR0cmlidXRlVmFsaWRhdGlvbkVycm9yLFxuICB0eXBlIENyZWF0ZUV2ZW50UmVxdWVzdCxcbiAgdHlwZSBTZXJpYWxpemVkRGF0YSxcbiAgU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gIFNQRUNfVkVSU0lPTl9TVVBQT1JUU19DT01QUkVTU0lPTixcbiAgdHlwZSBXb3JrZmxvd1J1bixcbiAgdHlwZSBXb3JsZCxcbn0gZnJvbSAnQHdvcmtmbG93L3dvcmxkJztcbmltcG9ydCB7IGltcG9ydEtleSB9IGZyb20gJy4uL2VuY3J5cHRpb24uanMnO1xuaW1wb3J0IHR5cGUge1xuICBBdHRyaWJ1dGVJbnZvY2F0aW9uUXVldWVJdGVtLFxuICBIb29rSW52b2NhdGlvblF1ZXVlSXRlbSxcbiAgU3RlcEludm9jYXRpb25RdWV1ZUl0ZW0sXG4gIFdhaXRJbnZvY2F0aW9uUXVldWVJdGVtLFxuICBXb3JrZmxvd1N1c3BlbnNpb24sXG59IGZyb20gJy4uL2dsb2JhbC5qcyc7XG5pbXBvcnQgeyBydW50aW1lTG9nZ2VyIH0gZnJvbSAnLi4vbG9nZ2VyLmpzJztcbmltcG9ydCB7IGRlaHlkcmF0ZVN0ZXBBcmd1bWVudHMgfSBmcm9tICcuLi9zZXJpYWxpemF0aW9uLmpzJztcbmltcG9ydCAqIGFzIEF0dHJpYnV0ZSBmcm9tICcuLi90ZWxlbWV0cnkvc2VtYW50aWMtY29udmVudGlvbnMuanMnO1xuaW1wb3J0IHsgZ2V0QWJvcnRTdHJlYW1JZEZyb21Ub2tlbiB9IGZyb20gJy4uL3V0aWwuanMnO1xuaW1wb3J0IHsgZ2V0TWF4SW5saW5lU3RlcHMgfSBmcm9tICcuL2NvbnN0YW50cy5qcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3VzcGVuc2lvbkhhbmRsZXJQYXJhbXMge1xuICBzdXNwZW5zaW9uOiBXb3JrZmxvd1N1c3BlbnNpb247XG4gIHdvcmxkOiBXb3JsZDtcbiAgcnVuOiBXb3JrZmxvd1J1bjtcbiAgc3Bhbj86IFNwYW47XG4gIHJlcXVlc3RJZD86IHN0cmluZztcbiAgLyoqXG4gICAqIFR1cmJvIG1vZGUgb25seTogYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgb25jZSB0aGUgYmFja2dyb3VuZGVkXG4gICAqIGBydW5fc3RhcnRlZGAgaGFzIGxhbmRlZCAodGhlIHJ1biBleGlzdHMpLiBXaGVuIHByZXNlbnQsIGV2ZXJ5IHdvcmxkIHdyaXRlXG4gICAqIHRoaXMgc3VzcGVuc2lvbiBwZXJmb3JtcyAoYGhvb2tfY3JlYXRlZGAsIGB3YWl0X2NyZWF0ZWRgLCBlYWdlciBvdmVyZmxvd1xuICAgKiBgc3RlcF9jcmVhdGVkYCwg4oCmKSBpcyBnYXRlZCBvbiBpdCBzbyB0aGUgd3JpdGUgbmV2ZXIgcmFjZXMgYWhlYWQgb2YgdGhlXG4gICAqIHJ1bidzIGNyZWF0aW9uLiBUaGUgcHVyZSBpbmxpbmUgaG90IHBhdGggZGVmZXJzIGFsbCBvZiBpdHMgc3RlcHMgYW5kIHdyaXRlc1xuICAgKiBub3RoaW5nIGhlcmUsIHNvIGl0IG5ldmVyIGF3YWl0cyB0aGlzIGJhcnJpZXIuIGB1bmRlZmluZWRgIG91dHNpZGUgdHVyYm8sXG4gICAqIHdoZXJlIGBydW5fc3RhcnRlZGAgd2FzIGFscmVhZHkgYXdhaXRlZCB1cCBmcm9udC5cbiAgICovXG4gIHJ1blJlYWR5QmFycmllcj86IFByb21pc2U8dW5rbm93bj47XG59XG5cbi8qKlxuICogUmVzdWx0IG9mIGhhbmRsaW5nIGEgc3VzcGVuc2lvbi4gUmV0dXJucyBwZW5kaW5nIHN0ZXAgaXRlbXMgc28gdGhlIGNhbGxlclxuICogY2FuIGRlY2lkZSB3aGljaCB0byBleGVjdXRlIGlubGluZSB2cyBxdWV1ZSB0byBiYWNrZ3JvdW5kLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFN1c3BlbnNpb25IYW5kbGVyUmVzdWx0IHtcbiAgLyoqIFBlbmRpbmcgc3RlcCBpdGVtcyB3aXRoIGV2ZW50cyBjcmVhdGVkIGJ1dCBOT1QgcXVldWVkICovXG4gIHBlbmRpbmdTdGVwczogU3RlcEludm9jYXRpb25RdWV1ZUl0ZW1bXTtcbiAgLyoqXG4gICAqIENvcnJlbGF0aW9uIElEcyBmb3Igd2hpY2ggdGhpcyBzdXNwZW5zaW9uIGNhbGwgYWN0dWFsbHkgd3JvdGUgdGhlXG4gICAqIHN0ZXBfY3JlYXRlZCBldmVudCAoYXMgb3Bwb3NlZCB0byBjYXRjaGluZyBFbnRpdHlDb25mbGljdEVycm9yIGJlY2F1c2VcbiAgICogYSBjb25jdXJyZW50IGhhbmRsZXIgd3JvdGUgaXQgZmlyc3QpLiBPbmx5IHRoZSBoYW5kbGVyIHRoYXQgd3JvdGUgdGhlXG4gICAqIHN0ZXBfY3JlYXRlZCBldmVudCBzaG91bGQgcXVldWUgLyBpbmxpbmUtZXhlY3V0ZSB0aGUgc3RlcCDigJQgdGhpc1xuICAgKiBndWFyYW50ZWVzIGEgc2luZ2xlIG93bmVyIHBlciBzdGVwLCBldmVuIHdoZW4gbXVsdGlwbGUgaGFuZGxlcnMgcmFjZVxuICAgKiBpbnRvIHRoZSBzYW1lIGJhdGNoIGJvdW5kYXJ5LlxuICAgKi9cbiAgY3JlYXRlZFN0ZXBDb3JyZWxhdGlvbklkczogU2V0PHN0cmluZz47XG4gIC8qKlxuICAgKiBUaGUgc3RlcHMgd2hvc2UgYHN0ZXBfY3JlYXRlZGAgd3JpdGVzIHdlcmUgaW50ZW50aW9uYWxseSBkZWZlcnJlZCBzbyB0aGVcbiAgICogY2FsbGVyIGNhbiBydW4gdGhlbSBpbmxpbmUgdmlhIGxhenkgYHN0ZXBfc3RhcnRlZGAgZXZlbnRzICh3aGljaCBjcmVhdGVcbiAgICogdGhlIHN0ZXAgb24gdGhlIGZseSksIHNhdmluZyBvbmUgd29ybGQgcm91bmQtdHJpcCBwZXIgaW5saW5lIHN0ZXAuIFVwIHRvXG4gICAqIGBnZXRNYXhJbmxpbmVTdGVwcygpYCBzdGVwcyBhcmUgZGVmZXJyZWQ7IHRoZSBjYWxsZXIgcnVucyB0aGVtIGlubGluZSBpblxuICAgKiBwYXJhbGxlbCBhbmQgcXVldWVzIHRoZSByZXN0LiBFbXB0eSB3aGVuIG5vIHN0ZXAgd2FzIGRlZmVycmVkIChub3RoaW5nXG4gICAqIHBlbmRpbmcsIG9yIGEgYGhvb2suZ2V0Q29uZmxpY3QoKWAgYXdhaXRlciBpcyBwcmVzZW50IHNvIG5vdGhpbmcgaXNcbiAgICogZXhlY3V0ZWQgaW5saW5lKS4gVGhlIGNhbGxlciBwYXNzZXMgZWFjaCBgZGVoeWRyYXRlZElucHV0YCBzdHJhaWdodCB0b1xuICAgKiBgZXhlY3V0ZVN0ZXBgLCB3aGljaCBzZW5kcyBpdCBhcyB0aGUgYHN0ZXBfc3RhcnRlZGAgcGF5bG9hZC4gVGhlIGF0b21pY1xuICAgKiBjcmVhdGUtY2xhaW0gaW5zaWRlIGVhY2ggYHN0ZXBfc3RhcnRlZGAgaXMgdGhlIGV4YWN0bHktb25lLW93bmVyIGdhdGUgdGhhdFxuICAgKiB0aGUgc3RhbmRhbG9uZSBgc3RlcF9jcmVhdGVkYCBwcm92aWRlZCBiZWZvcmU6IHRoZSBsb3NlciBvZiB0aGUgcmFjZSBnZXRzXG4gICAqIGBFbnRpdHlDb25mbGljdEVycm9yYCDihpIgYHNraXBwZWRgIGFuZCBkb2VzIG5vdCBydW4gdGhlIGJvZHkuXG4gICAqL1xuICBsYXp5SW5saW5lU3RlcHM6IEFycmF5PHtcbiAgICBjb3JyZWxhdGlvbklkOiBzdHJpbmc7XG4gICAgc3RlcE5hbWU6IHN0cmluZztcbiAgICBkZWh5ZHJhdGVkSW5wdXQ6IFNlcmlhbGl6ZWREYXRhO1xuICB9PjtcbiAgLyoqXG4gICAqIFRoZSBzb29uZXN0IHBlbmRpbmcgd2FpdCwgaWYgYW55OiBzZWNvbmRzIHVudGlsIGl0IGVsYXBzZXMgYW5kIHRoZVxuICAgKiBjb3JyZWxhdGlvbklkIG9mIHRoZSB3YWl0IHRoYXQgcHJvZHVjZWQgdGhhdCB0aW1lb3V0LiBUaGVcbiAgICogY29ycmVsYXRpb25JZCBzZWVkcyB0aGUgaWRlbXBvdGVuY3kga2V5IGZvciB0aGUgd2FpdC1jb250aW51YXRpb25cbiAgICogcXVldWUgbWVzc2FnZSBzbyB0aGF0IHJlcGVhdGVkIHN1c3BlbnNpb24gcGFzc2VzIG92ZXIgdGhlIHNhbWVcbiAgICogcGVuZGluZyB3YWl0IGNvbGxhcHNlIGludG8gYSBzaW5nbGUgZGVsYXllZCBjb250aW51YXRpb24uXG4gICAqL1xuICB3YWl0VGltZW91dD86IHsgc2Vjb25kczogbnVtYmVyOyBjb3JyZWxhdGlvbklkOiBzdHJpbmcgfTtcbiAgLyoqIFdoZXRoZXIgYSBob29rIGNvbmZsaWN0IHdhcyBkZXRlY3RlZCAoc2hvdWxkIHJlLWludm9rZSBpbW1lZGlhdGVseSkgKi9cbiAgaGFzSG9va0NvbmZsaWN0OiBib29sZWFuO1xuICAvKiogV2hldGhlciBhIGBob29rLmdldENvbmZsaWN0KClgIGF3YWl0ZXIgbmVlZHMgdGhlIHdvcmtmbG93IHRvIGNvbnRpbnVlIGltbWVkaWF0ZWx5ICovXG4gIGhhc0F3YWl0ZWRIb29rQ3JlYXRpb246IGJvb2xlYW47XG4gIC8qKiBXaGV0aGVyIG5hdGl2ZSB3b3JrZmxvdyBhdHRyaWJ1dGUgZXZlbnRzIHdlcmUgd3JpdHRlbiBmb3IgcmVwbGF5LiAqL1xuICBoYXNBdHRyaWJ1dGVFdmVudHM6IGJvb2xlYW47XG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoaXMgc3VzcGVuc2lvbiBjcmVhdGVkIGFueSBob29rIChgaG9va19jcmVhdGVkYCkgZXZlbnRzLiBVbmxpa2VcbiAgICogYGhhc0hvb2tDb25mbGljdGAgLyBgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbmAsIHRoaXMgaXMgdHJ1ZSBldmVuIGZvciBhIHBsYWluXG4gICAqIGZpcmUtYW5kLWZvcmdldCBob29rIHdpdGggbm8gY29uZmxpY3QgYW5kIG5vIGF3YWl0ZXIuIFR1cmJvIG1vZGUgdXNlcyBpdCB0b1xuICAgKiBkZXRlY3QgXCJhIGhvb2sgd2FzIGNyZWF0ZWQgdGhpcyBzdXNwZW5zaW9uXCIgYW5kIHN0b3AgZm9yY2luZyBvcHRpbWlzdGljXG4gICAqIGlubGluZSBzdGFydCAoYSBob29rIGludHJvZHVjZXMgbGF0ZXIgcmVzdW1lIGludm9jYXRpb25zIHRoYXQgY291bGQgcmFjZSkuXG4gICAqL1xuICBoYXNIb29rRXZlbnRzOiBib29sZWFuO1xuICAvKipcbiAgICogV2FsbC1jbG9jayBtcyBzcGVudCBjb21taXR0aW5nIHRoaXMgc3VzcGVuc2lvbidzIGBob29rX2NyZWF0ZWRgIGV2ZW50c1xuICAgKiAoMCB3aGVuIGl0IGNyZWF0ZWQgbm9uZSkuIFRoZSBjYWxsZXIgYWNjdW11bGF0ZXMgdGhpcyBhY3Jvc3MgaXRlcmF0aW9uc1xuICAgKiBhbmQgc3VidHJhY3RzIGl0IGZyb20gdGhlIFRURlMgbGF0ZW5jeSBtZWFzdXJlbWVudCwgc28gdGltZSBzcGVudFxuICAgKiBkdXJhYmx5IGNyZWF0aW5nIHRoZSB1c2VyJ3MgaG9va3MgZG9lc24ndCBjb3VudCBhcyBydW50aW1lIG92ZXJoZWFkLlxuICAgKi9cbiAgaG9va0NyZWF0aW9uTXM6IG51bWJlcjtcbn1cblxuYXN5bmMgZnVuY3Rpb24gY3JlYXRlSG9va0V2ZW50KHtcbiAgd29ybGQsXG4gIHJ1bklkLFxuICBob29rRXZlbnQsXG4gIHF1ZXVlSXRlbSxcbiAgcmVxdWVzdElkLFxufToge1xuICB3b3JsZDogV29ybGQ7XG4gIHJ1bklkOiBzdHJpbmc7XG4gIGhvb2tFdmVudDogQ3JlYXRlRXZlbnRSZXF1ZXN0O1xuICBxdWV1ZUl0ZW06IEhvb2tJbnZvY2F0aW9uUXVldWVJdGVtO1xuICByZXF1ZXN0SWQ/OiBzdHJpbmc7XG59KTogUHJvbWlzZTx7XG4gIGhhc0hvb2tDb25mbGljdDogYm9vbGVhbjtcbiAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbjogYm9vbGVhbjtcbn0+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKHJ1bklkLCBob29rRXZlbnQsIHtcbiAgICAgIHJlcXVlc3RJZCxcbiAgICB9KTtcblxuICAgIC8vIENoZWNrIGlmIHRoZSB3b3JsZCByZXR1cm5lZCBhIGhvb2tfY29uZmxpY3QgZXZlbnQgaW5zdGVhZCBvZiBob29rX2NyZWF0ZWQuXG4gICAgLy8gVGhlIGhvb2tfY29uZmxpY3QgZXZlbnQgaXMgc3RvcmVkIGluIHRoZSBldmVudCBsb2cgYW5kIHdpbGwgYmUgcmVwbGF5ZWRcbiAgICAvLyBvbiB0aGUgbmV4dCB3b3JrZmxvdyBpbnZvY2F0aW9uLCBjYXVzaW5nIHRoZSBob29rJ3MgcHJvbWlzZSB0byByZWplY3QuXG4gICAgaWYgKHJlc3VsdC5ldmVudD8uZXZlbnRUeXBlID09PSAnaG9va19jb25mbGljdCcpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGhhc0hvb2tDb25mbGljdDogdHJ1ZSxcbiAgICAgICAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbjogZmFsc2UsXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBoYXNIb29rQ29uZmxpY3Q6IGZhbHNlLFxuICAgICAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbjogcXVldWVJdGVtLmhhc0NvbmZsaWN0QXdhaXRlciA9PT0gdHJ1ZSxcbiAgICB9O1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ0hvb2sgYWxyZWFkeSBleGlzdHMsIGNvbnRpbnVpbmcnLCB7XG4gICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaGFzSG9va0NvbmZsaWN0OiBmYWxzZSxcbiAgICAgICAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbjogcXVldWVJdGVtLmhhc0NvbmZsaWN0QXdhaXRlciA9PT0gdHJ1ZSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKFJ1bkV4cGlyZWRFcnJvci5pcyhlcnIpKSB7XG4gICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ1dvcmtmbG93IHJ1biBhbHJlYWR5IGNvbXBsZXRlZCwgc2tpcHBpbmcgaG9vaycsIHtcbiAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgfSk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBoYXNIb29rQ29uZmxpY3Q6IGZhbHNlLFxuICAgICAgICBoYXNBd2FpdGVkSG9va0NyZWF0aW9uOiBmYWxzZSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgdGhyb3cgZXJyO1xuICB9XG59XG5cbi8qKlxuICogSGFuZGxlcyBhIHdvcmtmbG93IHN1c3BlbnNpb24gYnkgcHJvY2Vzc2luZyBhbGwgcGVuZGluZyBvcGVyYXRpb25zIChob29rcywgc3RlcHMsIHdhaXRzKS5cbiAqIENyZWF0ZXMgZXZlbnRzIGZvciBhbGwgb3BlcmF0aW9ucyBidXQgZG9lcyBOT1QgcXVldWUgc3RlcCBtZXNzYWdlcyDigJQgcmV0dXJucyB0aGUgcGVuZGluZ1xuICogc3RlcHMgc28gdGhlIGNhbGxlciBjYW4gZGVjaWRlIHdoaWNoIHRvIGV4ZWN1dGUgaW5saW5lIHZzIHF1ZXVlIHRvIGJhY2tncm91bmQuXG4gKlxuICogUHJvY2Vzc2luZyBvcmRlcjpcbiAqIDEuIEhvb2tzIGFyZSBwcm9jZXNzZWQgZmlyc3QgdG8gcHJldmVudCByYWNlIGNvbmRpdGlvbnMgd2l0aCB3ZWJob29rIHJlY2VpdmVyc1xuICogMi4gU3RlcCBldmVudHMgYW5kIHdhaXQgZXZlbnRzIGFyZSBjcmVhdGVkIGluIHBhcmFsbGVsXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYW5kbGVTdXNwZW5zaW9uKHtcbiAgc3VzcGVuc2lvbixcbiAgd29ybGQsXG4gIHJ1bixcbiAgc3BhbixcbiAgcmVxdWVzdElkLFxuICBydW5SZWFkeUJhcnJpZXIsXG59OiBTdXNwZW5zaW9uSGFuZGxlclBhcmFtcyk6IFByb21pc2U8U3VzcGVuc2lvbkhhbmRsZXJSZXN1bHQ+IHtcbiAgY29uc3QgcnVuSWQgPSBydW4ucnVuSWQ7XG4gIC8vIFR1cmJvIG1vZGU6IGhvbGQgZXZlcnkgd29ybGQgd3JpdGUgYmVsb3cgdW50aWwgdGhlIGJhY2tncm91bmRlZFxuICAvLyBgcnVuX3N0YXJ0ZWRgIGhhcyAqc2V0dGxlZCosIHNvIHdlIG5ldmVyIHdyaXRlIGEgc3RlcC9ob29rL3dhaXQgZXZlbnQgZm9yIGFcbiAgLy8gcnVuIHRoYXQgZG9lcyBub3QgZXhpc3QgeWV0LiBBIG5vLW9wIG91dHNpZGUgdHVyYm8gKGJhcnJpZXIgdW5kZWZpbmVkKSBhbmRcbiAgLy8gb24gdGhlIHB1cmUgaW5saW5lIGhvdCBwYXRoLCB3aGljaCBkZWZlcnMgYWxsIHN0ZXBzIGFuZCB3cml0ZXMgbm90aGluZy5cbiAgLy8gQXdhaXRpbmcgdGhlIHNhbWUgKHVzdWFsbHkgYWxyZWFkeS1zZXR0bGVkKSBwcm9taXNlIG1vcmUgdGhhbiBvbmNlIGlzIGNoZWFwLlxuICAvLyBBIGJhcnJpZXIgcmVqZWN0aW9uIGlzIHN3YWxsb3dlZCBmb3Igb3JkZXJpbmcgb25seTogaWYgYHJ1bl9zdGFydGVkYCB0cnVseVxuICAvLyBmYWlsZWQgdGhlIHJ1biBkb2VzIG5vdCBleGlzdCwgc28gdGhlIHN1YnNlcXVlbnQgd3JpdGUgc3VyZmFjZXMgdGhlIHJlYWxcbiAgLy8gZXJyb3IgKHJ1biBub3QgZm91bmQgLyBnb25lKSBhbmQgdGhlIG1lc3NhZ2UgcmVkZWxpdmVycy5cbiAgY29uc3QgZW5zdXJlUnVuUmVhZHkgPSBhc3luYyAoKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgaWYgKHJ1blJlYWR5QmFycmllcikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgcnVuUmVhZHlCYXJyaWVyO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIGludGVudGlvbmFsOiBvcmRlcmluZyBiYXJyaWVyIG9ubHkg4oCUIHNlZSBhYm92ZS5cbiAgICAgIH1cbiAgICB9XG4gIH07XG4gIC8vIFNlcGFyYXRlIHF1ZXVlIGl0ZW1zIGJ5IHR5cGVcbiAgY29uc3Qgc3RlcEl0ZW1zID0gc3VzcGVuc2lvbi5zdGVwcy5maWx0ZXIoXG4gICAgKGl0ZW0pOiBpdGVtIGlzIFN0ZXBJbnZvY2F0aW9uUXVldWVJdGVtID0+IGl0ZW0udHlwZSA9PT0gJ3N0ZXAnXG4gICk7XG4gIGNvbnN0IGFsbEhvb2tJdGVtcyA9IHN1c3BlbnNpb24uc3RlcHMuZmlsdGVyKFxuICAgIChpdGVtKTogaXRlbSBpcyBIb29rSW52b2NhdGlvblF1ZXVlSXRlbSA9PiBpdGVtLnR5cGUgPT09ICdob29rJ1xuICApO1xuICBjb25zdCB3YWl0SXRlbXMgPSBzdXNwZW5zaW9uLnN0ZXBzLmZpbHRlcihcbiAgICAoaXRlbSk6IGl0ZW0gaXMgV2FpdEludm9jYXRpb25RdWV1ZUl0ZW0gPT4gaXRlbS50eXBlID09PSAnd2FpdCdcbiAgKTtcbiAgY29uc3QgYXR0cmlidXRlSXRlbXMgPSBzdXNwZW5zaW9uLnN0ZXBzLmZpbHRlcihcbiAgICAoaXRlbSk6IGl0ZW0gaXMgQXR0cmlidXRlSW52b2NhdGlvblF1ZXVlSXRlbSA9PiBpdGVtLnR5cGUgPT09ICdhdHRyaWJ1dGUnXG4gICk7XG5cbiAgY29uc3QgaG9va3NOZWVkaW5nQ3JlYXRpb24gPSBhbGxIb29rSXRlbXMuZmlsdGVyKFxuICAgIChpdGVtKSA9PiAhaXRlbS5oYXNDcmVhdGVkRXZlbnRcbiAgKTtcblxuICAvLyBHcm91cCBob29rIGl0ZW1zIHRoYXQgbmVlZCB3b3JrIGJ5IHRva2VuLCBwcmVzZXJ2aW5nIHF1ZXVlLWluc2VydGlvblxuICAvLyAod29ya2Zsb3cgY29kZSkgb3JkZXIgd2l0aGluIGVhY2ggdG9rZW4uIE9wZXJhdGlvbnMgb24gb25lIHRva2VuIG11c3RcbiAgLy8gYXBwbHkgaW4gY29kZSBvcmRlcjogYSBkaXNwb3NlKCkgb2YgYW4gZWFybGllciBob29rIHJlbGVhc2VzIHRoZSB0b2tlblxuICAvLyBiZWZvcmUgYSBsYXRlciBzYW1lLXRva2VuIGhvb2sncyBjcmVhdGlvbiBpcyB2YWxpZGF0ZWQg4oCUIG90aGVyd2lzZSB0aGVcbiAgLy8gbmV3IGhvb2sgcmVjb3JkcyBhIHNwdXJpb3VzIGhvb2tfY29uZmxpY3QgYWdhaW5zdCB0aGUgcnVuJ3Mgb3duXG4gIC8vIGRpc3Bvc2VkIGhvb2sg4oCUIHdoaWxlIGEgaG9vayBjcmVhdGVkIGFuZCBkaXNwb3NlZCB3aXRoaW4gdGhlIHNhbWVcbiAgLy8gc3VzcGVuc2lvbiBpcyBzdGlsbCBjcmVhdGVkIGJlZm9yZSBpdCBpcyBkaXNwb3NlZC4gRGlmZmVyZW50IHRva2Vuc1xuICAvLyBoYXZlIG5vIGNsYWltIGludGVyYWN0aW9uLCBzbyB0b2tlbiBncm91cHMgYXJlIHByb2Nlc3NlZCBpbiBwYXJhbGxlbC5cbiAgY29uc3QgaG9va0l0ZW1zQnlUb2tlbiA9IG5ldyBNYXA8c3RyaW5nLCBIb29rSW52b2NhdGlvblF1ZXVlSXRlbVtdPigpO1xuICBmb3IgKGNvbnN0IGl0ZW0gb2YgYWxsSG9va0l0ZW1zKSB7XG4gICAgaWYgKGl0ZW0uaGFzQ3JlYXRlZEV2ZW50ICYmICFpdGVtLmRpc3Bvc2VkKSB7XG4gICAgICBjb250aW51ZTsgLy8gYWxyZWFkeSBjb21taXR0ZWQgYW5kIHN0aWxsIGxpdmUg4oCUIG5vdGhpbmcgdG8gZG9cbiAgICB9XG4gICAgY29uc3QgZ3JvdXAgPSBob29rSXRlbXNCeVRva2VuLmdldChpdGVtLnRva2VuKTtcbiAgICBpZiAoZ3JvdXApIHtcbiAgICAgIGdyb3VwLnB1c2goaXRlbSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGhvb2tJdGVtc0J5VG9rZW4uc2V0KGl0ZW0udG9rZW4sIFtpdGVtXSk7XG4gICAgfVxuICB9XG5cbiAgLy8gUmVzb2x2ZSBlbmNyeXB0aW9uIGtleSBmb3IgdGhpcyBydW5cbiAgY29uc3QgcmF3S2V5ID0gYXdhaXQgd29ybGQuZ2V0RW5jcnlwdGlvbktleUZvclJ1bj8uKHJ1bik7XG4gIGNvbnN0IGVuY3J5cHRpb25LZXkgPSByYXdLZXkgPyBhd2FpdCBpbXBvcnRLZXkocmF3S2V5KSA6IHVuZGVmaW5lZDtcblxuICAvLyBHYXRlIHBheWxvYWQgY29tcHJlc3Npb24gb24gdGhlIHJ1bidzIHNwZWNWZXJzaW9uOiBvbmx5IHJ1bnMgbWFya2VkXG4gIC8vIGFzIHBvc3NpYmx5IGNvbnRhaW5pbmcgY29tcHJlc3NlZCBwYXlsb2FkcyAoc3BlYyA+PSA1KSBnZXQgZ3ppcCBkYXRhLlxuICBjb25zdCBjb21wcmVzc2lvbiA9XG4gICAgKHJ1bi5zcGVjVmVyc2lvbiA/PyAwKSA+PSBTUEVDX1ZFUlNJT05fU1VQUE9SVFNfQ09NUFJFU1NJT047XG5cbiAgYXN5bmMgZnVuY3Rpb24gZGlzcG9zZUhvb2soXG4gICAgcXVldWVJdGVtOiBIb29rSW52b2NhdGlvblF1ZXVlSXRlbVxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBob29rRGlzcG9zZWRFdmVudDogQ3JlYXRlRXZlbnRSZXF1ZXN0ID0ge1xuICAgICAgZXZlbnRUeXBlOiAnaG9va19kaXNwb3NlZCcgYXMgY29uc3QsXG4gICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICB0b2tlbjogcXVldWVJdGVtLnRva2VuLFxuICAgICAgfSxcbiAgICB9O1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKHJ1bklkLCBob29rRGlzcG9zZWRFdmVudCwgeyByZXF1ZXN0SWQgfSk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBpZiAoRW50aXR5Q29uZmxpY3RFcnJvci5pcyhlcnIpKSB7XG4gICAgICAgIC8vIEhvb2sgd2FzIGFscmVhZHkgZGlzcG9zZWQgYnkgYSBjb25jdXJyZW50IGludm9jYXRpb24g4oCUIHNhZmUgdG8gc2tpcFxuICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgJ0hvb2sgYWxyZWFkeSBkaXNwb3NlZCwgc2tpcHBpbmcgZHVwbGljYXRlIGRpc3Bvc2FsJyxcbiAgICAgICAgICB7XG4gICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgfSBlbHNlIGlmIChSdW5FeHBpcmVkRXJyb3IuaXMoZXJyKSkge1xuICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oXG4gICAgICAgICAgJ1dvcmtmbG93IHJ1biBhbHJlYWR5IGNvbXBsZXRlZCwgc2tpcHBpbmcgaG9vayBkaXNwb3NhbCcsXG4gICAgICAgICAge1xuICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSBpZiAoSG9va05vdEZvdW5kRXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAvLyBIb29rIG1heSBoYXZlIGFscmVhZHkgYmVlbiBkaXNwb3NlZCBvciBuZXZlciBjcmVhdGVkXG4gICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbygnSG9vayBub3QgZm91bmQgZm9yIGRpc3Bvc2FsLCBjb250aW51aW5nJywge1xuICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBQcm9jZXNzIGhvb2tzIGZpcnN0IHRvIHByZXZlbnQgcmFjZSBjb25kaXRpb25zIHdpdGggd2ViaG9vayByZWNlaXZlcnMuXG4gIC8vIFRyYWNrIGFueSBob29rIGNvbmZsaWN0cyB0aGF0IG9jY3VyIOKAlCB0aGVzZSBhcmUgcmV0dXJuZWQgdG8gdGhlIGNhbGxlclxuICAvLyBzbyB0aGUgVjIgaGFuZGxlciBjYW4gcmUtaW52b2tlIGltbWVkaWF0ZWx5LlxuICBsZXQgaGFzSG9va0NvbmZsaWN0ID0gZmFsc2U7XG4gIGxldCBoYXNBd2FpdGVkSG9va0NyZWF0aW9uID0gZmFsc2U7XG4gIGxldCBob29rQ3JlYXRpb25NcyA9IDA7XG5cbiAgaWYgKGhvb2tJdGVtc0J5VG9rZW4uc2l6ZSA+IDApIHtcbiAgICBjb25zdCBob29rUGhhc2VTdGFydCA9IERhdGUubm93KCk7XG4gICAgYXdhaXQgZW5zdXJlUnVuUmVhZHkoKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIFsuLi5ob29rSXRlbXNCeVRva2VuLnZhbHVlcygpXS5tYXAoYXN5bmMgKGl0ZW1zKSA9PiB7XG4gICAgICAgIGZvciAoY29uc3QgcXVldWVJdGVtIG9mIGl0ZW1zKSB7XG4gICAgICAgICAgbGV0IGNyZWF0aW9uQ29uZmxpY3RlZCA9IGZhbHNlO1xuXG4gICAgICAgICAgaWYgKCFxdWV1ZUl0ZW0uaGFzQ3JlYXRlZEV2ZW50KSB7XG4gICAgICAgICAgICBjb25zdCBob29rTWV0YWRhdGE6IFNlcmlhbGl6ZWREYXRhIHwgdW5kZWZpbmVkID1cbiAgICAgICAgICAgICAgdHlwZW9mIHF1ZXVlSXRlbS5tZXRhZGF0YSA9PT0gJ3VuZGVmaW5lZCdcbiAgICAgICAgICAgICAgICA/IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgIDogKChhd2FpdCBkZWh5ZHJhdGVTdGVwQXJndW1lbnRzKFxuICAgICAgICAgICAgICAgICAgICBxdWV1ZUl0ZW0ubWV0YWRhdGEsXG4gICAgICAgICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICAgICAgICBlbmNyeXB0aW9uS2V5LFxuICAgICAgICAgICAgICAgICAgICBzdXNwZW5zaW9uLmdsb2JhbFRoaXMsXG4gICAgICAgICAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBjb21wcmVzc2lvblxuICAgICAgICAgICAgICAgICAgKSkgYXMgU2VyaWFsaXplZERhdGEpO1xuICAgICAgICAgICAgY29uc3QgaG9va0V2ZW50OiBDcmVhdGVFdmVudFJlcXVlc3QgPSB7XG4gICAgICAgICAgICAgIGV2ZW50VHlwZTogJ2hvb2tfY3JlYXRlZCcgYXMgY29uc3QsXG4gICAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICAgIHRva2VuOiBxdWV1ZUl0ZW0udG9rZW4sXG4gICAgICAgICAgICAgICAgbWV0YWRhdGE6IGhvb2tNZXRhZGF0YSxcbiAgICAgICAgICAgICAgICBpc1dlYmhvb2s6IHF1ZXVlSXRlbS5pc1dlYmhvb2sgPz8gZmFsc2UsXG4gICAgICAgICAgICAgICAgLi4uKHF1ZXVlSXRlbS5pc1N5c3RlbSAmJiB7IGlzU3lzdGVtOiB0cnVlIH0pLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNyZWF0ZUhvb2tFdmVudCh7XG4gICAgICAgICAgICAgIHdvcmxkLFxuICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgaG9va0V2ZW50LFxuICAgICAgICAgICAgICBxdWV1ZUl0ZW0sXG4gICAgICAgICAgICAgIHJlcXVlc3RJZCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaGFzSG9va0NvbmZsaWN0IHx8PSByZXN1bHQuaGFzSG9va0NvbmZsaWN0O1xuICAgICAgICAgICAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbiB8fD0gcmVzdWx0Lmhhc0F3YWl0ZWRIb29rQ3JlYXRpb247XG4gICAgICAgICAgICBjcmVhdGlvbkNvbmZsaWN0ZWQgPSByZXN1bHQuaGFzSG9va0NvbmZsaWN0O1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIERpc3Bvc2UgYWZ0ZXIgY3JlYXRpb24gZm9yIGhvb2tzIGJvcm4gYW5kIGRpc3Bvc2VkIHdpdGhpbiB0aGlzXG4gICAgICAgICAgLy8gYmF0Y2guIEEgaG9vayB3aG9zZSBjcmVhdGlvbiBjb25mbGljdGVkIHdhcyBuZXZlciBjcmVhdGVkLCBzb1xuICAgICAgICAgIC8vIHRoZXJlIGlzIG5vdGhpbmcgdG8gZGlzcG9zZS5cbiAgICAgICAgICBpZiAocXVldWVJdGVtLmRpc3Bvc2VkICYmICFjcmVhdGlvbkNvbmZsaWN0ZWQpIHtcbiAgICAgICAgICAgIGF3YWl0IGRpc3Bvc2VIb29rKHF1ZXVlSXRlbSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KVxuICAgICk7XG4gICAgaG9va0NyZWF0aW9uTXMgPSBEYXRlLm5vdygpIC0gaG9va1BoYXNlU3RhcnQ7XG4gIH1cblxuICAvLyBQcm9jZXNzIGFib3J0IHJlcXVlc3RzIOKAlCByZXN1bWUgdGhlIGhvb2sgd2l0aCBhYm9ydCBwYXlsb2FkIGFuZCB3cml0ZSBzdHJlYW0gcGFja2V0XG4gIGNvbnN0IGhvb2tzTmVlZGluZ0Fib3J0ID0gYWxsSG9va0l0ZW1zLmZpbHRlcihcbiAgICAoaXRlbSkgPT4gaXRlbS5hYm9ydFJlcXVlc3RlZCAmJiAhaXRlbS5kaXNwb3NlZFxuICApO1xuXG4gIGlmIChob29rc05lZWRpbmdBYm9ydC5sZW5ndGggPiAwKSB7XG4gICAgYXdhaXQgZW5zdXJlUnVuUmVhZHkoKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIGhvb2tzTmVlZGluZ0Fib3J0Lm1hcChhc3luYyAocXVldWVJdGVtKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgLy8gRGVoeWRyYXRlIHRoZSBhYm9ydCBwYXlsb2FkIGZvciBzdG9yYWdlXG4gICAgICAgICAgY29uc3QgYWJvcnRQYXlsb2FkID0gYXdhaXQgZGVoeWRyYXRlU3RlcEFyZ3VtZW50cyhcbiAgICAgICAgICAgIHsgYWJvcnRlZDogdHJ1ZSwgcmVhc29uOiBxdWV1ZUl0ZW0uYWJvcnRSZWFzb24gfSxcbiAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgZW5jcnlwdGlvbktleSxcbiAgICAgICAgICAgIHN1c3BlbnNpb24uZ2xvYmFsVGhpcyxcbiAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgY29tcHJlc3Npb25cbiAgICAgICAgICApO1xuXG4gICAgICAgICAgLy8gQ3JlYXRlIGhvb2tfcmVjZWl2ZWQgZXZlbnQgd2l0aCBhYm9ydCBwYXlsb2FkXG4gICAgICAgICAgYXdhaXQgd29ybGQuZXZlbnRzLmNyZWF0ZShydW5JZCwge1xuICAgICAgICAgICAgZXZlbnRUeXBlOiAnaG9va19yZWNlaXZlZCcgYXMgY29uc3QsXG4gICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgIGV2ZW50RGF0YToge1xuICAgICAgICAgICAgICB0b2tlbjogcXVldWVJdGVtLnRva2VuLFxuICAgICAgICAgICAgICBwYXlsb2FkOiBhYm9ydFBheWxvYWQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgLy8gV3JpdGUgc3RyZWFtIGNhbmNlbGxhdGlvbiBwYWNrZXQgZm9yIHJlYWwtdGltZSBzdGVwIHByb3BhZ2F0aW9uLlxuICAgICAgICAgIC8vIFJldXNlIHRoZSBzYW1lIGRlaHlkcmF0ZWQgcGF5bG9hZCBhcyB0aGUgaG9vayBldmVudCBzbyB0aGUgcmVhc29uXG4gICAgICAgICAgLy8gcm91bmQtdHJpcHMgdGhyb3VnaCBgZGVoeWRyYXRlU3RlcEFyZ3VtZW50c2AgLyBgaHlkcmF0ZVN0ZXBBcmd1bWVudHNgXG4gICAgICAgICAgLy8gKGhhbmRsZXMgRE9NRXhjZXB0aW9uLCBjdXN0b20gZXJyb3JzLCBlbmNyeXB0aW9uLCBldGMuKSBpbnN0ZWFkIG9mXG4gICAgICAgICAgLy8gYmFyZSBKU09OLnN0cmluZ2lmeSB3aGljaCBsb3NlcyB0eXBlIGluZm9ybWF0aW9uIGFuZCBkcm9wcyB1bmRlZmluZWQuXG4gICAgICAgICAgLy8gc3RyZWFtTmFtZSBpcyBzZXQgb24gdGhlIHF1ZXVlIGl0ZW0gYXQgY29udHJvbGxlciBjb25zdHJ1Y3Rpb24gdGltZVxuICAgICAgICAgIC8vIChzZWUgd29ya2Zsb3cvYWJvcnQtY29udHJvbGxlci50cykuXG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHN0cmVhbU5hbWUgPSBnZXRBYm9ydFN0cmVhbUlkRnJvbVRva2VuKHF1ZXVlSXRlbS50b2tlbik7XG4gICAgICAgICAgICBhd2FpdCB3b3JsZC5zdHJlYW1zLndyaXRlKFxuICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgc3RyZWFtTmFtZSxcbiAgICAgICAgICAgICAgYWJvcnRQYXlsb2FkIGFzIFVpbnQ4QXJyYXlcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBhd2FpdCB3b3JsZC5zdHJlYW1zLmNsb3NlKHJ1bklkLCBzdHJlYW1OYW1lKTtcbiAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIC8vIEJlc3QtZWZmb3J0IHN0cmVhbSB3cml0ZSDigJQgaG9vayBldmVudCBwcm92aWRlcyB0aGUgZHVyYWJsZSBmYWxsYmFja1xuICAgICAgICAgICAgcnVudGltZUxvZ2dlci5kZWJ1ZyhcbiAgICAgICAgICAgICAgJ0ZhaWxlZCB0byB3cml0ZSBhYm9ydCBzdHJlYW0gcGFja2V0LCBob29rIGV2ZW50IHdpbGwgcHJvdmlkZSBmYWxsYmFjaycsXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB3b3JrZmxvd1J1bklkOiBydW5JZCxcbiAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikgfHwgUnVuRXhwaXJlZEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgIHJ1bnRpbWVMb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgJ1dvcmtmbG93IHJ1biBhbHJlYWR5IGNvbXBsZXRlZCwgc2tpcHBpbmcgYWJvcnQnLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIC8vIENyZWF0ZSBzdGVwIGV2ZW50cyBmb3Igc3RlcHMgdGhhdCBkb24ndCBoYXZlIHRoZW0geWV0LlxuICAvLyBVbmxpa2UgVjEsIHdlIGRvIE5PVCBxdWV1ZSBzdGVwIG1lc3NhZ2VzIGZyb20gaGVyZSDigJQgdGhlIGNhbGxlclxuICAvLyBkZWNpZGVzIHdoaWNoIHN0ZXBzIHRvIGV4ZWN1dGUgaW5saW5lIHZzLiBxdWV1ZSB0byBiYWNrZ3JvdW5kLlxuICAvLyBXYWl0IGV2ZW50cyBhcmUgYWxzbyBjcmVhdGVkIGluIHBhcmFsbGVsIGJlbG93LlxuICBjb25zdCBzdGVwc05lZWRpbmdDcmVhdGlvbiA9IG5ldyBTZXQoXG4gICAgc3RlcEl0ZW1zXG4gICAgICAuZmlsdGVyKChxdWV1ZUl0ZW0pID0+ICFxdWV1ZUl0ZW0uaGFzQ3JlYXRlZEV2ZW50KVxuICAgICAgLm1hcCgocXVldWVJdGVtKSA9PiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZClcbiAgKTtcblxuICAvLyBDb3JyZWxhdGlvbiBJRHMgZm9yIHdoaWNoIFRISVMgc3VzcGVuc2lvbiBjYWxsIGFjdHVhbGx5IHdyb3RlIHRoZVxuICAvLyBzdGVwX2NyZWF0ZWQgZXZlbnQuIFBvcHVsYXRlZCBieSB0aGUgb3BzIGJlbG93IGFmdGVyIGEgc3VjY2Vzc2Z1bFxuICAvLyBldmVudHMuY3JlYXRlIOKAlCB1c2VkIGJ5IHRoZSBjYWxsZXIgdG8gY2xhaW0gb3duZXJzaGlwIGFuZCBhdm9pZFxuICAvLyByYWNpbmcgd2l0aCBjb25jdXJyZW50IGhhbmRsZXJzIG9uIHN0ZXAgZXhlY3V0aW9uLlxuICBjb25zdCBjcmVhdGVkU3RlcENvcnJlbGF0aW9uSWRzID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgLy8gTGF6eSBpbmxpbmUgc3RhcnQ6IGRlZmVyIHRoZSBzdGVwX2NyZWF0ZWQgd3JpdGUgZm9yIHVwIHRvXG4gIC8vIGBnZXRNYXhJbmxpbmVTdGVwcygpYCBzdGVwcyB0aGUgY2FsbGVyIHdpbGwgcnVuIGlubGluZSAoaW4gcGFyYWxsZWwpLiBFYWNoXG4gIC8vIHN0ZXAgaXMgY3JlYXRlZCBvbiB0aGUgZmx5IGJ5IHRoZSBsYXp5IGBzdGVwX3N0YXJ0ZWRgIGV4ZWN1dGVTdGVwIHNlbmRzXG4gIC8vIChzYXZpbmcgYSByb3VuZC10cmlwIHBlciBzdGVwKS4gV2UgbmV2ZXIgZGVmZXIgd2hlbiBhIGBob29rLmdldENvbmZsaWN0KClgXG4gIC8vIGF3YWl0ZXIgaXMgcHJlc2VudCwgYmVjYXVzZSBpbiB0aGF0IGNhc2UgdGhlIGNhbGxlciBleGVjdXRlcyBub3RoaW5nIGlubGluZVxuICAvLyAoaXQgcmUtaW52b2tlcyBpbW1lZGlhdGVseSB0byByZXNvbHZlIHRoZSBhd2FpdGVyKSwgc28gZGVmZXJyaW5nIHdvdWxkXG4gIC8vIGxlYXZlIHRoZSBzdGVwcyB1bmNyZWF0ZWQgYW5kIHVucXVldWVkLiBXZSBwaWNrIHRoZSBmaXJzdCBOIHVuY3JlYXRlZCBzdGVwc1xuICAvLyDigJQgbWF0Y2hpbmcgdGhlIGNhbGxlcidzIGlubGluZS1jYW5kaWRhdGUgc2VsZWN0aW9uIOKAlCBhbmQgZGVoeWRyYXRlIHRoZWlyXG4gIC8vIGlucHV0IGhlcmUgc28gZXhlY3V0ZVN0ZXAgY2FuIHNoaXAgaXQgYXMgdGhlIHN0ZXBfc3RhcnRlZCBwYXlsb2FkLlxuICBjb25zdCBsYXp5SW5saW5lQ29ycmVsYXRpb25JZHMgPSBuZXcgU2V0PHN0cmluZz4oXG4gICAgaGFzQXdhaXRlZEhvb2tDcmVhdGlvbiA9PT0gZmFsc2VcbiAgICAgID8gc3RlcEl0ZW1zXG4gICAgICAgICAgLmZpbHRlcigoaXRlbSkgPT4gc3RlcHNOZWVkaW5nQ3JlYXRpb24uaGFzKGl0ZW0uY29ycmVsYXRpb25JZCkpXG4gICAgICAgICAgLnNsaWNlKDAsIGdldE1heElubGluZVN0ZXBzKCkpXG4gICAgICAgICAgLm1hcCgoaXRlbSkgPT4gaXRlbS5jb3JyZWxhdGlvbklkKVxuICAgICAgOiBbXVxuICApO1xuICAvLyBDb2xsZWN0ZWQgYnkgY29ycmVsYXRpb25JZCBiZWNhdXNlIHRoZSBwZXItc3RlcCBvcHMgYmVsb3cgcnVuIGNvbmN1cnJlbnRseVxuICAvLyBhbmQgc2V0dGxlIG91dCBvZiBvcmRlci4gV2UgcmVidWlsZCB0aGUgYXJyYXkgaW4gZGV0ZXJtaW5pc3RpY1xuICAvLyBgbGF6eUlubGluZUNvcnJlbGF0aW9uSWRzYCBvcmRlciAodGhlIG9yZGVyZWQgc2xpY2UgYWJvdmUpIGFmdGVyIHRoZSBvcHNcbiAgLy8gc2V0dGxlLCBzbyB0aGUgaW5saW5lIGJhdGNoIG9yZGVyIGlzIHN0YWJsZSByZWdhcmRsZXNzIG9mIGRlaHlkcmF0aW9uIHRpbWluZy5cbiAgY29uc3QgbGF6eUlubGluZUJ5Q29ycmVsYXRpb25JZCA9IG5ldyBNYXA8XG4gICAgc3RyaW5nLFxuICAgIFN1c3BlbnNpb25IYW5kbGVyUmVzdWx0WydsYXp5SW5saW5lU3RlcHMnXVtudW1iZXJdXG4gID4oKTtcblxuICBjb25zdCBvcHM6IFByb21pc2U8dm9pZD5bXSA9IFtdO1xuXG4gIC8vIFN0ZXBzOiBjcmVhdGUgc3RlcF9jcmVhdGVkIGV2ZW50cyAobm8gcXVldWluZyDigJQgVjIgcmV0dXJucyBwZW5kaW5nIHN0ZXBzIHRvIGNhbGxlcilcbiAgZm9yIChjb25zdCBxdWV1ZUl0ZW0gb2Ygc3RlcEl0ZW1zKSB7XG4gICAgaWYgKHN0ZXBzTmVlZGluZ0NyZWF0aW9uLmhhcyhxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCkpIHtcbiAgICAgIG9wcy5wdXNoKFxuICAgICAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IGRlaHlkcmF0ZWRJbnB1dCA9IGF3YWl0IGRlaHlkcmF0ZVN0ZXBBcmd1bWVudHMoXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGFyZ3M6IHF1ZXVlSXRlbS5hcmdzLFxuICAgICAgICAgICAgICBjbG9zdXJlVmFyczogcXVldWVJdGVtLmNsb3N1cmVWYXJzLFxuICAgICAgICAgICAgICB0aGlzVmFsOiBxdWV1ZUl0ZW0udGhpc1ZhbCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgIGVuY3J5cHRpb25LZXksXG4gICAgICAgICAgICBzdXNwZW5zaW9uLmdsb2JhbFRoaXMsXG4gICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgIGNvbXByZXNzaW9uXG4gICAgICAgICAgKTtcbiAgICAgICAgICAvLyBEZWZlcnJlZCAobGF6eSkgaW5saW5lIHN0ZXA6IHNraXAgdGhlIHN0ZXBfY3JlYXRlZCB3cml0ZSDigJQgdGhlXG4gICAgICAgICAgLy8gY2FsbGVyJ3MgaW5saW5lIGV4ZWN1dGVTdGVwIHdpbGwgc2VuZCBhIGxhenkgc3RlcF9zdGFydGVkIGNhcnJ5aW5nXG4gICAgICAgICAgLy8gdGhpcyBpbnB1dCwgYW5kIHRoZSB3b3JsZCBjcmVhdGVzIHRoZSBzdGVwIChlbnRpdHkgKyBzeW50aGV0aWNcbiAgICAgICAgICAvLyBzdGVwX2NyZWF0ZWQgZXZlbnQpIGF0b21pY2FsbHkuIFdlIGRvIE5PVCBhZGQgaXQgdG9cbiAgICAgICAgICAvLyBjcmVhdGVkU3RlcENvcnJlbGF0aW9uSWRzOyBvd25lcnNoaXAgaXMgZGVjaWRlZCBieSB0aGF0IGxhenlcbiAgICAgICAgICAvLyBzdGVwX3N0YXJ0ZWQncyBhdG9taWMgY3JlYXRlLWNsYWltIGluc3RlYWQuXG4gICAgICAgICAgaWYgKGxhenlJbmxpbmVDb3JyZWxhdGlvbklkcy5oYXMocXVldWVJdGVtLmNvcnJlbGF0aW9uSWQpKSB7XG4gICAgICAgICAgICBsYXp5SW5saW5lQnlDb3JyZWxhdGlvbklkLnNldChxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCwge1xuICAgICAgICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgc3RlcE5hbWU6IHF1ZXVlSXRlbS5zdGVwTmFtZSxcbiAgICAgICAgICAgICAgZGVoeWRyYXRlZElucHV0OiBkZWh5ZHJhdGVkSW5wdXQgYXMgU2VyaWFsaXplZERhdGEsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3Qgc3RlcEV2ZW50OiBDcmVhdGVFdmVudFJlcXVlc3QgPSB7XG4gICAgICAgICAgICBldmVudFR5cGU6ICdzdGVwX2NyZWF0ZWQnIGFzIGNvbnN0LFxuICAgICAgICAgICAgc3BlY1ZlcnNpb246IFNQRUNfVkVSU0lPTl9DVVJSRU5ULFxuICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgc3RlcE5hbWU6IHF1ZXVlSXRlbS5zdGVwTmFtZSxcbiAgICAgICAgICAgICAgd29ya2Zsb3dOYW1lOiBydW4ud29ya2Zsb3dOYW1lLFxuICAgICAgICAgICAgICBpbnB1dDogZGVoeWRyYXRlZElucHV0IGFzIFNlcmlhbGl6ZWREYXRhLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9O1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBlbnN1cmVSdW5SZWFkeSgpO1xuICAgICAgICAgICAgYXdhaXQgd29ybGQuZXZlbnRzLmNyZWF0ZShydW5JZCwgc3RlcEV2ZW50LCB7IHJlcXVlc3RJZCB9KTtcbiAgICAgICAgICAgIGNyZWF0ZWRTdGVwQ29ycmVsYXRpb25JZHMuYWRkKHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkKTtcbiAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGlmIChFbnRpdHlDb25mbGljdEVycm9yLmlzKGVycikpIHtcbiAgICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKCdTdGVwIGFscmVhZHkgZXhpc3RzLCBjb250aW51aW5nJywge1xuICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pKClcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLy8gQ3JlYXRlIHdhaXQgZXZlbnRzIChzYW1lIGFzIFYxKVxuICBmb3IgKGNvbnN0IHF1ZXVlSXRlbSBvZiB3YWl0SXRlbXMpIHtcbiAgICBpZiAoIXF1ZXVlSXRlbS5oYXNDcmVhdGVkRXZlbnQpIHtcbiAgICAgIG9wcy5wdXNoKFxuICAgICAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHdhaXRFdmVudDogQ3JlYXRlRXZlbnRSZXF1ZXN0ID0ge1xuICAgICAgICAgICAgZXZlbnRUeXBlOiAnd2FpdF9jcmVhdGVkJyBhcyBjb25zdCxcbiAgICAgICAgICAgIHNwZWNWZXJzaW9uOiBTUEVDX1ZFUlNJT05fQ1VSUkVOVCxcbiAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgZXZlbnREYXRhOiB7XG4gICAgICAgICAgICAgIHJlc3VtZUF0OiBxdWV1ZUl0ZW0ucmVzdW1lQXQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH07XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IGVuc3VyZVJ1blJlYWR5KCk7XG4gICAgICAgICAgICBhd2FpdCB3b3JsZC5ldmVudHMuY3JlYXRlKHJ1bklkLCB3YWl0RXZlbnQsIHsgcmVxdWVzdElkIH0pO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgICBydW50aW1lTG9nZ2VyLmluZm8oJ1dhaXQgYWxyZWFkeSBleGlzdHMsIGNvbnRpbnVpbmcnLCB7XG4gICAgICAgICAgICAgICAgd29ya2Zsb3dSdW5JZDogcnVuSWQsXG4gICAgICAgICAgICAgICAgY29ycmVsYXRpb25JZDogcXVldWVJdGVtLmNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogZXJyLm1lc3NhZ2UsXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSkoKVxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBmb3IgKGNvbnN0IHF1ZXVlSXRlbSBvZiBhdHRyaWJ1dGVJdGVtcykge1xuICAgIG9wcy5wdXNoKFxuICAgICAgKGFzeW5jICgpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCBlbnN1cmVSdW5SZWFkeSgpO1xuICAgICAgICAgIGF3YWl0IHdvcmxkLmV2ZW50cy5jcmVhdGUoXG4gICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgZXZlbnRUeXBlOiAnYXR0cl9zZXQnLFxuICAgICAgICAgICAgICBzcGVjVmVyc2lvbjogU1BFQ19WRVJTSU9OX0NVUlJFTlQsXG4gICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICBldmVudERhdGE6IHtcbiAgICAgICAgICAgICAgICBjaGFuZ2VzOiBxdWV1ZUl0ZW0uY2hhbmdlcyxcbiAgICAgICAgICAgICAgICB3cml0ZXI6IHsgdHlwZTogJ3dvcmtmbG93JyB9LFxuICAgICAgICAgICAgICAgIC4uLihxdWV1ZUl0ZW0uYWxsb3dSZXNlcnZlZEF0dHJpYnV0ZXNcbiAgICAgICAgICAgICAgICAgID8geyBhbGxvd1Jlc2VydmVkQXR0cmlidXRlczogdHJ1ZSB9XG4gICAgICAgICAgICAgICAgICA6IHt9KSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7IHJlcXVlc3RJZCB9XG4gICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgaWYgKEVudGl0eUNvbmZsaWN0RXJyb3IuaXMoZXJyKSkge1xuICAgICAgICAgICAgcnVudGltZUxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAnV29ya2Zsb3cgYXR0cmlidXRlIGV2ZW50IGFscmVhZHkgZXhpc3RzLCBjb250aW51aW5nJyxcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHdvcmtmbG93UnVuSWQ6IHJ1bklkLFxuICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uSWQ6IHF1ZXVlSXRlbS5jb3JyZWxhdGlvbklkLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGVyci5tZXNzYWdlLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0gZWxzZSBpZiAoaXNBdHRyaWJ1dGVWYWxpZGF0aW9uRmFpbHVyZShlcnIpKSB7XG4gICAgICAgICAgICAvLyBEZXRlcm1pbmlzdGljIHZhbGlkYXRpb24gcmVqZWN0aW9uIGZyb20gdGhlIFdvcmxkIOKAlCBlLmcuIHRoZVxuICAgICAgICAgICAgLy8gY3VtdWxhdGl2ZSBwZXItcnVuIGF0dHJpYnV0ZSBjYXAsIHdoaWNoIG9ubHkgdGhlIFdvcmxkIGNhblxuICAgICAgICAgICAgLy8gY2hlY2sgYWdhaW5zdCB0aGUgcnVuJ3MgZXhpc3RpbmcgYXR0cmlidXRlcy4gUmVkZWxpdmVyaW5nIHRoZVxuICAgICAgICAgICAgLy8gb3JjaGVzdHJhdG9yIG1lc3NhZ2UgcmVwbGF5cyB0aGUgd29ya2Zsb3cgaW50byB0aGUgZXhhY3Qgc2FtZVxuICAgICAgICAgICAgLy8gd3JpdGUgYW5kIHRoZSBleGFjdCBzYW1lIHJlamVjdGlvbiwgc28gcmV0cnlpbmcgY2FuIG5ldmVyXG4gICAgICAgICAgICAvLyBzdWNjZWVkLiBTdXJmYWNlIGl0IGFzIGEgRmF0YWxFcnJvciBzbyB0aGUgY2FsbGVyIGZhaWxzIHRoZVxuICAgICAgICAgICAgLy8gcnVuIHdpdGggYSBjbGVhciBlcnJvciBpbnN0ZWFkIG9mIHdlZGdpbmcgaXQgaW4gcmVkZWxpdmVyeS5cbiAgICAgICAgICAgIGNvbnN0IGZhdGFsID0gbmV3IEZhdGFsRXJyb3IoXG4gICAgICAgICAgICAgIGBzZXRBdHRyaWJ1dGVzIGZhaWxlZCBXb3JsZCB2YWxpZGF0aW9uOiAke1xuICAgICAgICAgICAgICAgIGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKVxuICAgICAgICAgICAgICB9YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGZhdGFsLmNhdXNlID0gZXJyO1xuICAgICAgICAgICAgdGhyb3cgZmF0YWw7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pKClcbiAgICApO1xuICB9XG5cbiAgLy8gQXdhaXQgdGhlIHN0ZXBfY3JlYXRlZCAvIHdhaXRfY3JlYXRlZCBldmVudCBjcmVhdGVzIGJlZm9yZSByZXR1cm5pbmcuXG4gIC8vIFRoZSBjYWxsZXIgKHdvcmtmbG93RW50cnlwb2ludCkgb25seSBlbnF1ZXVlcyB0aGUgc3RlcC1kaXNwYXRjaCBxdWV1ZVxuICAvLyBtZXNzYWdlcyBBRlRFUiBoYW5kbGVTdXNwZW5zaW9uIHJlc29sdmVzLCBhbmQgdGhlIHF1ZXVlIGhhbmRsZXIgYWNrc1xuICAvLyB0aGUgb3JjaGVzdHJhdG9yIG1lc3NhZ2Ugb25seSBhZnRlciB0aGUgY2FsbGVyIHJlc29sdmVzLiBTbyB0aGUgc3RlcF9jcmVhdGVkXG4gIC8vIGV2ZW50cyBtdXN0IGJlIGR1cmFibGUgaGVyZSwgYW5kIHRoZSBkaXNwYXRjaCBzZW5kcyBtdXN0IGNvbXBsZXRlIGluIHRoZSBjYWxsZXIsXG4gIC8vIGFsbCBiZWZvcmUgYWNrLiBJZiB0aGUgcHJvY2VzcyBjcmFzaGVzIGJlZm9yZSB0aGlzIHJlc29sdmVzLCB0aGUgb3JjaGVzdHJhdG9yXG4gIC8vIG1lc3NhZ2UgaXMgbm90IGFja2VkIGFuZCBWUVMgcmVkZWxpdmVycywgcmUtY3JlYXRlcyB0aGUgKGlkZW1wb3RlbnQpXG4gIC8vIHN0ZXBfY3JlYXRlZCBhbmQgcmUtZGlzcGF0Y2hlcywgYW5kIHJlY292ZXJzIHRoZSBydW4gaW5zdGVhZCBvZiBvcnBoYW5pbmcgaXQuXG4gIGF3YWl0IFByb21pc2UuYWxsKG9wcyk7XG5cbiAgLy8gUmVidWlsZCB0aGUgaW5saW5lIGJhdGNoIGluIGRldGVybWluaXN0aWMgb3JkZXIuIGBsYXp5SW5saW5lQ29ycmVsYXRpb25JZHNgXG4gIC8vIGlzIGEgU2V0IHNlZWRlZCBmcm9tIHRoZSBvcmRlcmVkIGZpcnN0LU4gc2xpY2UsIHNvIGl0ZXJhdGluZyBpdCBwcmVzZXJ2ZXNcbiAgLy8gc3RlcEl0ZW1zIG9yZGVyOyBldmVyeSBpZCBpbiBpdCB3YXMgc2V0IGJ5IHRoZSBsYXp5IGJyYW5jaCBhYm92ZS5cbiAgY29uc3QgbGF6eUlubGluZVN0ZXBzOiBTdXNwZW5zaW9uSGFuZGxlclJlc3VsdFsnbGF6eUlubGluZVN0ZXBzJ10gPSBbXTtcbiAgZm9yIChjb25zdCBjb3JyZWxhdGlvbklkIG9mIGxhenlJbmxpbmVDb3JyZWxhdGlvbklkcykge1xuICAgIGNvbnN0IGxhenlTdGVwID0gbGF6eUlubGluZUJ5Q29ycmVsYXRpb25JZC5nZXQoY29ycmVsYXRpb25JZCk7XG4gICAgaWYgKGxhenlTdGVwKSBsYXp5SW5saW5lU3RlcHMucHVzaChsYXp5U3RlcCk7XG4gIH1cblxuICAvLyBGaW5kIHRoZSBzb29uZXN0IHBlbmRpbmcgd2FpdCAobWluaW11bSB0aW1lb3V0KVxuICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICBsZXQgc29vbmVzdFdhaXQ6IHsgc2Vjb25kczogbnVtYmVyOyBjb3JyZWxhdGlvbklkOiBzdHJpbmcgfSB8IHVuZGVmaW5lZDtcbiAgZm9yIChjb25zdCBxdWV1ZUl0ZW0gb2Ygd2FpdEl0ZW1zKSB7XG4gICAgY29uc3QgcmVzdW1lQXRNcyA9IHF1ZXVlSXRlbS5yZXN1bWVBdC5nZXRUaW1lKCk7XG4gICAgY29uc3QgZGVsYXlNcyA9IE1hdGgubWF4KDEwMDAsIHJlc3VtZUF0TXMgLSBub3cpO1xuICAgIGNvbnN0IHRpbWVvdXRTZWNvbmRzID0gTWF0aC5jZWlsKGRlbGF5TXMgLyAxMDAwKTtcbiAgICBpZiAoIXNvb25lc3RXYWl0IHx8IHRpbWVvdXRTZWNvbmRzIDwgc29vbmVzdFdhaXQuc2Vjb25kcykge1xuICAgICAgc29vbmVzdFdhaXQgPSB7XG4gICAgICAgIHNlY29uZHM6IHRpbWVvdXRTZWNvbmRzLFxuICAgICAgICBjb3JyZWxhdGlvbklkOiBxdWV1ZUl0ZW0uY29ycmVsYXRpb25JZCxcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgc3Bhbj8uc2V0QXR0cmlidXRlcyh7XG4gICAgLi4uQXR0cmlidXRlLldvcmtmbG93UnVuU3RhdHVzKCd3b3JrZmxvd19zdXNwZW5kZWQnKSxcbiAgICAuLi5BdHRyaWJ1dGUuV29ya2Zsb3dTdGVwc0NyZWF0ZWQoc3RlcEl0ZW1zLmxlbmd0aCksXG4gICAgLi4uQXR0cmlidXRlLldvcmtmbG93SG9va3NDcmVhdGVkKGhvb2tzTmVlZGluZ0NyZWF0aW9uLmxlbmd0aCksXG4gICAgLi4uQXR0cmlidXRlLldvcmtmbG93V2FpdHNDcmVhdGVkKHdhaXRJdGVtcy5sZW5ndGgpLFxuICB9KTtcblxuICByZXR1cm4ge1xuICAgIHBlbmRpbmdTdGVwczogc3RlcEl0ZW1zLFxuICAgIGNyZWF0ZWRTdGVwQ29ycmVsYXRpb25JZHMsXG4gICAgbGF6eUlubGluZVN0ZXBzLFxuICAgIC8vIE9uIGhvb2sgY29uZmxpY3QgdGhlIGNhbGxlciByZS1pbnZva2VzIGltbWVkaWF0ZWx5IGFuZCBuZXZlciByZWFkc1xuICAgIC8vIHRoZSB3YWl0IHRpbWVvdXQsIHNvIGRvbid0IHJlcG9ydCBvbmUuXG4gICAgd2FpdFRpbWVvdXQ6IGhhc0hvb2tDb25mbGljdCA/IHVuZGVmaW5lZCA6IHNvb25lc3RXYWl0LFxuICAgIGhhc0hvb2tDb25mbGljdCxcbiAgICBoYXNBd2FpdGVkSG9va0NyZWF0aW9uLFxuICAgIGhhc0F0dHJpYnV0ZUV2ZW50czogYXR0cmlidXRlSXRlbXMubGVuZ3RoID4gMCxcbiAgICBoYXNIb29rRXZlbnRzOiBob29rc05lZWRpbmdDcmVhdGlvbi5sZW5ndGggPiAwLFxuICAgIGhvb2tDcmVhdGlvbk1zLFxuICB9O1xufVxuXG4vKipcbiAqIFdoZXRoZXIgYW4gYGV2ZW50cy5jcmVhdGVgIHJlamVjdGlvbiBpcyBhIGRldGVybWluaXN0aWMgYXR0cmlidXRlXG4gKiB2YWxpZGF0aW9uIGZhaWx1cmUgcmF0aGVyIHRoYW4gYSB0cmFuc2llbnQvc3RvcmFnZSBlcnJvci4gTG9jYWwgV29ybGRzXG4gKiAod29ybGQtbG9jYWwsIHdvcmxkLXBvc3RncmVzKSB0aHJvdyBgQXR0cmlidXRlVmFsaWRhdGlvbkVycm9yYCBkaXJlY3RseTtcbiAqIHJlbW90ZSBXb3JsZHMgc3VyZmFjZSB0aGUgZXF1aXZhbGVudCBzZXJ2ZXItc2lkZSByZWplY3Rpb24gYXMgYVxuICogYFdvcmtmbG93V29ybGRFcnJvcmAgd2l0aCBIVFRQIHN0YXR1cyA0MDAuIFRoZSBuYW1lIGNoZWNrIGNvdmVyc1xuICogYEF0dHJpYnV0ZVZhbGlkYXRpb25FcnJvcmAgaW5zdGFuY2VzIGZyb20gYSBkaWZmZXJlbnQgY29weSBvZlxuICogYEB3b3JrZmxvdy93b3JsZGAgdGhhbiB0aGUgb25lIHRoaXMgcGFja2FnZSByZXNvbHZlZC5cbiAqL1xuZnVuY3Rpb24gaXNBdHRyaWJ1dGVWYWxpZGF0aW9uRmFpbHVyZShlcnI6IHVua25vd24pOiBib29sZWFuIHtcbiAgaWYgKGVyciBpbnN0YW5jZW9mIEF0dHJpYnV0ZVZhbGlkYXRpb25FcnJvcikgcmV0dXJuIHRydWU7XG4gIGlmIChlcnIgaW5zdGFuY2VvZiBFcnJvciAmJiBlcnIubmFtZSA9PT0gJ0F0dHJpYnV0ZVZhbGlkYXRpb25FcnJvcicpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICByZXR1cm4gV29ya2Zsb3dXb3JsZEVycm9yLmlzKGVycikgJiYgZXJyLnN0YXR1cyA9PT0gNDAwO1xufVxuIl19
|