@workflow/core 5.0.0-beta.2 → 5.0.0-beta.21

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.
Files changed (251) hide show
  1. package/dist/attribute-changes.d.ts +7 -0
  2. package/dist/attribute-changes.d.ts.map +1 -0
  3. package/dist/attribute-changes.js +25 -0
  4. package/dist/capabilities.d.ts +22 -1
  5. package/dist/capabilities.d.ts.map +1 -1
  6. package/dist/capabilities.js +41 -4
  7. package/dist/capture-stack.d.ts +16 -0
  8. package/dist/capture-stack.d.ts.map +1 -0
  9. package/dist/capture-stack.js +21 -0
  10. package/dist/class-serialization.d.ts +32 -0
  11. package/dist/class-serialization.d.ts.map +1 -1
  12. package/dist/class-serialization.js +37 -1
  13. package/dist/classify-error.d.ts +11 -3
  14. package/dist/classify-error.d.ts.map +1 -1
  15. package/dist/classify-error.js +59 -6
  16. package/dist/context-errors.d.ts +27 -0
  17. package/dist/context-errors.d.ts.map +1 -0
  18. package/dist/context-errors.js +101 -0
  19. package/dist/context-violation-error.d.ts +97 -0
  20. package/dist/context-violation-error.d.ts.map +1 -0
  21. package/dist/context-violation-error.js +147 -0
  22. package/dist/create-hook.d.ts +40 -1
  23. package/dist/create-hook.d.ts.map +1 -1
  24. package/dist/create-hook.js +4 -3
  25. package/dist/define-hook.d.ts.map +1 -1
  26. package/dist/define-hook.js +20 -5
  27. package/dist/describe-error.d.ts +70 -0
  28. package/dist/describe-error.d.ts.map +1 -0
  29. package/dist/describe-error.js +165 -0
  30. package/dist/encryption.d.ts +22 -1
  31. package/dist/encryption.d.ts.map +1 -1
  32. package/dist/encryption.js +72 -27
  33. package/dist/events-consumer.d.ts +24 -0
  34. package/dist/events-consumer.d.ts.map +1 -1
  35. package/dist/events-consumer.js +79 -16
  36. package/dist/flushable-stream.d.ts +10 -10
  37. package/dist/flushable-stream.d.ts.map +1 -1
  38. package/dist/flushable-stream.js +18 -13
  39. package/dist/global.d.ts +15 -1
  40. package/dist/global.d.ts.map +1 -1
  41. package/dist/global.js +21 -3
  42. package/dist/index.d.ts +1 -0
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +2 -1
  45. package/dist/log-format.d.ts +25 -0
  46. package/dist/log-format.d.ts.map +1 -0
  47. package/dist/log-format.js +250 -0
  48. package/dist/logger.d.ts +28 -30
  49. package/dist/logger.d.ts.map +1 -1
  50. package/dist/logger.js +77 -31
  51. package/dist/private.d.ts +107 -2
  52. package/dist/private.d.ts.map +1 -1
  53. package/dist/private.js +80 -3
  54. package/dist/runtime/constants.d.ts +121 -0
  55. package/dist/runtime/constants.d.ts.map +1 -1
  56. package/dist/runtime/constants.js +206 -8
  57. package/dist/runtime/get-port-lazy.d.ts +25 -0
  58. package/dist/runtime/get-port-lazy.d.ts.map +1 -0
  59. package/dist/runtime/get-port-lazy.js +92 -0
  60. package/dist/runtime/get-world-lazy.d.ts +32 -0
  61. package/dist/runtime/get-world-lazy.d.ts.map +1 -0
  62. package/dist/runtime/get-world-lazy.js +56 -0
  63. package/dist/runtime/helpers.d.ts +50 -7
  64. package/dist/runtime/helpers.d.ts.map +1 -1
  65. package/dist/runtime/helpers.js +149 -31
  66. package/dist/runtime/replay-budget.d.ts +98 -0
  67. package/dist/runtime/replay-budget.d.ts.map +1 -0
  68. package/dist/runtime/replay-budget.js +191 -0
  69. package/dist/runtime/resume-hook.d.ts.map +1 -1
  70. package/dist/runtime/resume-hook.js +39 -23
  71. package/dist/runtime/run-id-time.d.ts +10 -0
  72. package/dist/runtime/run-id-time.d.ts.map +1 -0
  73. package/dist/runtime/run-id-time.js +31 -0
  74. package/dist/runtime/run.d.ts.map +1 -1
  75. package/dist/runtime/run.js +44 -9
  76. package/dist/runtime/runs.d.ts.map +1 -1
  77. package/dist/runtime/runs.js +4 -1
  78. package/dist/runtime/start.d.ts +30 -1
  79. package/dist/runtime/start.d.ts.map +1 -1
  80. package/dist/runtime/start.js +138 -20
  81. package/dist/runtime/step-executor.d.ts +108 -0
  82. package/dist/runtime/step-executor.d.ts.map +1 -0
  83. package/dist/runtime/step-executor.js +715 -0
  84. package/dist/runtime/step-handler.d.ts.map +1 -1
  85. package/dist/runtime/step-handler.js +715 -556
  86. package/dist/runtime/suspension-handler.d.ts +74 -7
  87. package/dist/runtime/suspension-handler.d.ts.map +1 -1
  88. package/dist/runtime/suspension-handler.js +308 -116
  89. package/dist/runtime/wait-continuation.d.ts +84 -0
  90. package/dist/runtime/wait-continuation.d.ts.map +1 -0
  91. package/dist/runtime/wait-continuation.js +92 -0
  92. package/dist/runtime/wait-until.d.ts +18 -0
  93. package/dist/runtime/wait-until.d.ts.map +1 -0
  94. package/dist/runtime/wait-until.js +42 -0
  95. package/dist/runtime/world-init.d.ts +75 -0
  96. package/dist/runtime/world-init.d.ts.map +1 -0
  97. package/dist/runtime/world-init.js +75 -0
  98. package/dist/runtime/world.d.ts.map +1 -1
  99. package/dist/runtime/world.js +47 -18
  100. package/dist/runtime.d.ts +11 -8
  101. package/dist/runtime.d.ts.map +1 -1
  102. package/dist/runtime.js +1395 -319
  103. package/dist/schemas.d.ts +1 -1
  104. package/dist/schemas.d.ts.map +1 -1
  105. package/dist/schemas.js +1 -1
  106. package/dist/serialization/client.d.ts +17 -0
  107. package/dist/serialization/client.d.ts.map +1 -0
  108. package/dist/serialization/client.js +48 -0
  109. package/dist/serialization/codec-devalue.d.ts +14 -0
  110. package/dist/serialization/codec-devalue.d.ts.map +1 -0
  111. package/dist/serialization/codec-devalue.js +98 -0
  112. package/dist/serialization/codec.d.ts +106 -0
  113. package/dist/serialization/codec.d.ts.map +1 -0
  114. package/dist/serialization/codec.js +17 -0
  115. package/dist/serialization/compression.d.ts +104 -0
  116. package/dist/serialization/compression.d.ts.map +1 -0
  117. package/dist/serialization/compression.js +260 -0
  118. package/dist/serialization/encryption.d.ts +33 -0
  119. package/dist/serialization/encryption.d.ts.map +1 -0
  120. package/dist/serialization/encryption.js +70 -0
  121. package/dist/serialization/errors.d.ts +34 -0
  122. package/dist/serialization/errors.d.ts.map +1 -0
  123. package/dist/serialization/errors.js +59 -0
  124. package/dist/serialization/format.d.ts +60 -0
  125. package/dist/serialization/format.d.ts.map +1 -0
  126. package/dist/serialization/format.js +97 -0
  127. package/dist/serialization/index.d.ts +19 -0
  128. package/dist/serialization/index.d.ts.map +1 -0
  129. package/dist/serialization/index.js +22 -0
  130. package/dist/serialization/reducers/class.d.ts +11 -0
  131. package/dist/serialization/reducers/class.d.ts.map +1 -0
  132. package/dist/serialization/reducers/class.js +68 -0
  133. package/dist/serialization/reducers/common.d.ts +16 -0
  134. package/dist/serialization/reducers/common.d.ts.map +1 -0
  135. package/dist/serialization/reducers/common.js +417 -0
  136. package/dist/serialization/reducers/step-function.d.ts +35 -0
  137. package/dist/serialization/reducers/step-function.d.ts.map +1 -0
  138. package/dist/serialization/reducers/step-function.js +88 -0
  139. package/dist/serialization/step.d.ts +17 -0
  140. package/dist/serialization/step.d.ts.map +1 -0
  141. package/dist/serialization/step.js +48 -0
  142. package/dist/serialization/types.d.ts +253 -0
  143. package/dist/serialization/types.d.ts.map +1 -0
  144. package/dist/serialization/types.js +25 -0
  145. package/dist/serialization/workflow.d.ts +29 -0
  146. package/dist/serialization/workflow.d.ts.map +1 -0
  147. package/dist/serialization/workflow.js +54 -0
  148. package/dist/serialization-format.d.ts +15 -0
  149. package/dist/serialization-format.d.ts.map +1 -1
  150. package/dist/serialization-format.js +209 -11
  151. package/dist/serialization.d.ts +313 -214
  152. package/dist/serialization.d.ts.map +1 -1
  153. package/dist/serialization.js +1430 -658
  154. package/dist/set-attributes.d.ts +13 -0
  155. package/dist/set-attributes.d.ts.map +1 -0
  156. package/dist/set-attributes.js +42 -0
  157. package/dist/sleep.d.ts.map +1 -1
  158. package/dist/sleep.js +3 -2
  159. package/dist/source-map.d.ts +5 -0
  160. package/dist/source-map.d.ts.map +1 -1
  161. package/dist/source-map.js +102 -10
  162. package/dist/step/context-storage.d.ts +43 -0
  163. package/dist/step/context-storage.d.ts.map +1 -1
  164. package/dist/step/context-storage.js +1 -1
  165. package/dist/step/get-closure-vars.d.ts.map +1 -1
  166. package/dist/step/get-closure-vars.js +3 -2
  167. package/dist/step/get-step-metadata.d.ts.map +1 -1
  168. package/dist/step/get-step-metadata.js +3 -2
  169. package/dist/step/get-workflow-metadata.d.ts.map +1 -1
  170. package/dist/step/get-workflow-metadata.js +3 -2
  171. package/dist/step/writable-stream.d.ts.map +1 -1
  172. package/dist/step/writable-stream.js +49 -5
  173. package/dist/step-hydration-cache.d.ts +148 -0
  174. package/dist/step-hydration-cache.d.ts.map +1 -0
  175. package/dist/step-hydration-cache.js +171 -0
  176. package/dist/step.d.ts.map +1 -1
  177. package/dist/step.js +115 -21
  178. package/dist/symbols.d.ts +28 -0
  179. package/dist/symbols.d.ts.map +1 -1
  180. package/dist/symbols.js +29 -1
  181. package/dist/telemetry/semantic-conventions.d.ts +30 -2
  182. package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
  183. package/dist/telemetry/semantic-conventions.js +21 -1
  184. package/dist/telemetry.d.ts +60 -0
  185. package/dist/telemetry.d.ts.map +1 -1
  186. package/dist/telemetry.js +82 -4
  187. package/dist/types.d.ts +6 -0
  188. package/dist/types.d.ts.map +1 -1
  189. package/dist/types.js +23 -1
  190. package/dist/util.d.ts +16 -6
  191. package/dist/util.d.ts.map +1 -1
  192. package/dist/util.js +25 -16
  193. package/dist/version.d.ts +1 -1
  194. package/dist/version.d.ts.map +1 -1
  195. package/dist/version.js +2 -2
  196. package/dist/vm/index.d.ts.map +1 -1
  197. package/dist/vm/index.js +3 -2
  198. package/dist/vm/script-cache.d.ts +28 -0
  199. package/dist/vm/script-cache.d.ts.map +1 -0
  200. package/dist/vm/script-cache.js +140 -0
  201. package/dist/workflow/abort-controller.d.ts +65 -0
  202. package/dist/workflow/abort-controller.d.ts.map +1 -0
  203. package/dist/workflow/abort-controller.js +277 -0
  204. package/dist/workflow/attribute-dispatcher.d.ts +6 -0
  205. package/dist/workflow/attribute-dispatcher.d.ts.map +1 -0
  206. package/dist/workflow/attribute-dispatcher.js +48 -0
  207. package/dist/workflow/create-hook.d.ts.map +1 -1
  208. package/dist/workflow/create-hook.js +23 -2
  209. package/dist/workflow/define-hook.d.ts +1 -1
  210. package/dist/workflow/define-hook.d.ts.map +1 -1
  211. package/dist/workflow/define-hook.js +8 -4
  212. package/dist/workflow/get-workflow-metadata.d.ts.map +1 -1
  213. package/dist/workflow/get-workflow-metadata.js +14 -3
  214. package/dist/workflow/hook.d.ts.map +1 -1
  215. package/dist/workflow/hook.js +207 -33
  216. package/dist/workflow/index.d.ts +1 -0
  217. package/dist/workflow/index.d.ts.map +1 -1
  218. package/dist/workflow/index.js +5 -3
  219. package/dist/workflow/set-attributes.d.ts +73 -0
  220. package/dist/workflow/set-attributes.d.ts.map +1 -0
  221. package/dist/workflow/set-attributes.js +65 -0
  222. package/dist/workflow/sleep.d.ts.map +1 -1
  223. package/dist/workflow/sleep.js +45 -8
  224. package/dist/workflow/world-init-stub.d.ts +15 -0
  225. package/dist/workflow/world-init-stub.d.ts.map +1 -0
  226. package/dist/workflow/world-init-stub.js +15 -0
  227. package/dist/workflow.d.ts +10 -1
  228. package/dist/workflow.d.ts.map +1 -1
  229. package/dist/workflow.js +168 -49
  230. package/docs/api-reference/create-hook.mdx +38 -0
  231. package/docs/api-reference/create-webhook.mdx +1 -0
  232. package/docs/api-reference/experimental-set-attributes.mdx +65 -0
  233. package/docs/api-reference/fetch.mdx +5 -0
  234. package/docs/api-reference/index.mdx +3 -0
  235. package/docs/foundations/cancellation.mdx +459 -0
  236. package/docs/foundations/errors-and-retries.mdx +7 -3
  237. package/docs/foundations/hooks.mdx +29 -0
  238. package/docs/foundations/idempotency.mdx +236 -11
  239. package/docs/foundations/index.mdx +3 -3
  240. package/docs/foundations/meta.json +3 -2
  241. package/docs/foundations/serialization.mdx +78 -42
  242. package/docs/foundations/starting-workflows.mdx +6 -2
  243. package/docs/foundations/streaming.mdx +14 -23
  244. package/docs/foundations/versioning.mdx +263 -0
  245. package/docs/how-it-works/cancellation.mdx +287 -0
  246. package/docs/how-it-works/code-transform.mdx +2 -2
  247. package/docs/how-it-works/encryption.mdx +2 -2
  248. package/docs/how-it-works/event-sourcing.mdx +2 -2
  249. package/docs/how-it-works/meta.json +2 -1
  250. package/package.json +22 -10
  251. package/docs/foundations/common-patterns.mdx +0 -265
@@ -1,161 +1,42 @@
1
- import { types } from 'node:util';
2
- import { WorkflowRuntimeError } from '@workflow/errors';
3
- import { WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE } from '@workflow/serde';
4
- import { DevalueError, parse, stringify, unflatten } from 'devalue';
1
+ import { RuntimeDecryptionError, SerializationError, WorkflowRuntimeError, } from '@workflow/errors';
2
+ import { parse, stringify, unflatten } from 'devalue';
5
3
  import { monotonicFactory } from 'ulid';
6
- import { getSerializationClass } from './class-serialization.js';
7
- import { decrypt as aesGcmDecrypt, encrypt as aesGcmEncrypt, } from './encryption.js';
4
+ import { decrypt as aesGcmDecrypt, encrypt as aesGcmEncrypt, importKey, } from './encryption.js';
8
5
  import { createFlushableState, flushablePipe, pollReadableLock, pollWritableLock, } from './flushable-stream.js';
9
- import { runtimeLogger } from './logger.js';
10
6
  import { getStepFunction } from './private.js';
11
- import { getWorld } from './runtime/world.js';
7
+ // V2: use getWorldLazy in step-side code paths so Turbopack can statically
8
+ // resolve the world bridge from the step bundle without dragging the full
9
+ // world.ts module (and its dynamic-import behaviour) into the flow route.
10
+ // See `packages/core/src/runtime/get-world-lazy.ts` and the
11
+ // "Turbopack NFT Tracing Errors in V2 Combined Flow Route" section of
12
+ // `docs/content/docs/changelog/eager-processing.mdx`.
13
+ import { getWorldLazy } from './runtime/get-world-lazy.js';
14
+ import * as clientModule from './serialization/client.js';
15
+ import { compress, decompress, } from './serialization/compression.js';
16
+ import { decrypt, encrypt, resolveEncryptionKey, } from './serialization/encryption.js';
17
+ import { formatSerializationError, rethrowIfRuntimeError, } from './serialization/errors.js';
18
+ import { decodeFormatPrefix, encodeWithFormatPrefix, isEncrypted, peekFormatPrefix, } from './serialization/format.js';
19
+ import { getClassReducers, getClassRevivers, } from './serialization/reducers/class.js';
20
+ import { getCommonReducers, getCommonRevivers as getCommonReviversFromModule, revive, } from './serialization/reducers/common.js';
21
+ import { getStepFunctionReducer, getStepFunctionReviver, } from './serialization/reducers/step-function.js';
22
+ import * as stepModule from './serialization/step.js';
23
+ import { isFormatPrefix, SerializationFormat, } from './serialization/types.js';
24
+ import * as workflowModule from './serialization/workflow.js';
12
25
  import { contextStorage } from './step/context-storage.js';
13
- import { BODY_INIT_SYMBOL, STABLE_ULID, STREAM_NAME_SYMBOL, STREAM_TYPE_SYMBOL, WEBHOOK_RESPONSE_WRITABLE, } from './symbols.js';
14
- // ============================================================================
15
- // Serialization Format Prefix System
16
- // ============================================================================
17
- //
18
- // All serialized payloads are prefixed with a 4-byte format identifier that
19
- // allows the client to determine how to decode the payload. This enables:
20
- //
21
- // 1. Self-describing payloads - The World layer is agnostic to serialization format
22
- // 2. Gradual migration - Old runs keep working, new runs can use new formats
23
- // 3. Composability - Encryption can wrap any format (e.g., "encr" wrapping "devl")
24
- // 4. Debugging - Raw data inspection immediately reveals the format
25
- //
26
- // Format: [4 bytes: format identifier][payload]
27
- //
28
- // The 4-character prefix convention matches other workflow IDs (wrun, step, wait, etc.)
29
- //
30
- // Current formats:
31
- // - "devl" - devalue stringify/parse with TextEncoder/TextDecoder (current default)
32
- // - "encr" - Encrypted payload (inner payload has its own format prefix)
33
- //
34
- // Future formats (reserved):
35
- // - "cbor" - CBOR binary serialization
36
- /**
37
- * Known serialization format identifiers.
38
- * Each format ID is exactly 4 ASCII characters, matching the convention
39
- * used for other workflow IDs (wrun, step, wait, etc.)
40
- */
41
- export const SerializationFormat = {
42
- /** devalue stringify/parse with TextEncoder/TextDecoder */
43
- DEVALUE_V1: 'devl',
44
- /** Encrypted payload (inner payload has its own format prefix) */
45
- ENCRYPTED: 'encr',
46
- };
47
- /** Length of the format prefix in bytes */
48
- const FORMAT_PREFIX_LENGTH = 4;
49
- /** TextEncoder instance for format prefix encoding */
50
- const formatEncoder = new TextEncoder();
51
- /** TextDecoder instance for format prefix decoding */
52
- const formatDecoder = new TextDecoder();
53
- /**
54
- * Encode a payload with a format prefix.
55
- *
56
- * @param format - The format identifier (must be exactly 4 ASCII characters)
57
- * @param payload - The serialized payload bytes
58
- * @returns A new Uint8Array with format prefix prepended
59
- */
60
- export function encodeWithFormatPrefix(format, payload) {
61
- if (!(payload instanceof Uint8Array)) {
62
- return payload;
63
- }
64
- const prefixBytes = formatEncoder.encode(format);
65
- if (prefixBytes.length !== FORMAT_PREFIX_LENGTH) {
66
- throw new Error(`Format identifier must be exactly ${FORMAT_PREFIX_LENGTH} ASCII characters, got "${format}" (${prefixBytes.length} bytes)`);
67
- }
68
- const result = new Uint8Array(FORMAT_PREFIX_LENGTH + payload.length);
69
- result.set(prefixBytes, 0);
70
- result.set(payload, FORMAT_PREFIX_LENGTH);
71
- return result;
72
- }
73
- /**
74
- * Peek at the format prefix without consuming it.
75
- * Useful for checking if data is encrypted before deciding how to process it.
76
- *
77
- * @param data - The format-prefixed data
78
- * @returns The format identifier, or null if data is legacy/non-binary
79
- */
80
- export function peekFormatPrefix(data) {
81
- if (!(data instanceof Uint8Array) || data.length < FORMAT_PREFIX_LENGTH) {
82
- return null;
83
- }
84
- const prefixBytes = data.subarray(0, FORMAT_PREFIX_LENGTH);
85
- const format = formatDecoder.decode(prefixBytes);
86
- const knownFormats = Object.values(SerializationFormat);
87
- if (!knownFormats.includes(format)) {
88
- return null;
89
- }
90
- return format;
91
- }
92
- /**
93
- * Check if data is encrypted (has 'encr' format prefix).
94
- *
95
- * @param data - The format-prefixed data
96
- * @returns true if data has the encrypted format prefix
97
- */
98
- export function isEncrypted(data) {
99
- return peekFormatPrefix(data) === SerializationFormat.ENCRYPTED;
100
- }
101
- /**
102
- * Decode a format-prefixed payload.
103
- *
104
- * @param data - The format-prefixed data
105
- * @returns An object with the format identifier and payload
106
- * @throws Error if the data is too short or has an unknown format
107
- */
108
- export function decodeFormatPrefix(data) {
109
- // Compat for legacy specVersion 1 runs that don't have a format prefix,
110
- // and don't have a binary payload
111
- if (!(data instanceof Uint8Array)) {
112
- return {
113
- format: SerializationFormat.DEVALUE_V1,
114
- payload: new TextEncoder().encode(JSON.stringify(data)),
115
- };
116
- }
117
- if (data.length < FORMAT_PREFIX_LENGTH) {
118
- throw new Error(`Data too short to contain format prefix: expected at least ${FORMAT_PREFIX_LENGTH} bytes, got ${data.length}`);
119
- }
120
- const prefixBytes = data.subarray(0, FORMAT_PREFIX_LENGTH);
121
- const format = formatDecoder.decode(prefixBytes);
122
- // Validate the format is known
123
- const knownFormats = Object.values(SerializationFormat);
124
- if (!knownFormats.includes(format)) {
125
- throw new WorkflowRuntimeError(`Unknown serialization format: "${format}". Known formats: ${knownFormats.join(', ')}`);
126
- }
127
- const payload = data.subarray(FORMAT_PREFIX_LENGTH);
128
- return { format: format, payload };
129
- }
26
+ import { ABORT_HOOK_TOKEN, ABORT_LISTENER_ATTACHED, ABORT_READER_CANCEL, ABORT_STREAM_NAME, BODY_INIT_SYMBOL, STABLE_ULID, STREAM_FRAMING_SYMBOL, STREAM_NAME_SYMBOL, STREAM_SERVER_DEPLOYMENT_ID_SYMBOL, STREAM_SERVER_RUN_ID_SYMBOL, STREAM_TYPE_SYMBOL, WEBHOOK_RESPONSE_WRITABLE, } from './symbols.js';
27
+ import * as Attr from './telemetry/semantic-conventions.js';
28
+ import { getActiveSpan } from './telemetry.js';
29
+ import { getAbortStreamId } from './util.js';
30
+ import { WorkflowAbortSignal } from './workflow/abort-controller.js';
31
+ // Re-export types and utilities from the modular serialization modules
32
+ // so existing consumers of `@workflow/core/serialization` keep working.
33
+ export { SerializationFormat, isFormatPrefix, encodeWithFormatPrefix, decodeFormatPrefix, peekFormatPrefix, isEncrypted, encrypt, decrypt, compress, decompress, };
130
34
  /**
131
35
  * Default ULID generator for contexts where VM's seeded `stableUlid` isn't available.
132
36
  * Used as a fallback when serializing streams outside the workflow VM context
133
37
  * (e.g., when starting a workflow or handling step return values).
134
38
  */
135
39
  const defaultUlid = monotonicFactory();
136
- /**
137
- * Format a serialization error with context about what failed.
138
- * Extracts path, value, and reason from devalue's DevalueError when available.
139
- * Logs the problematic value to the console for better debugging.
140
- */
141
- function formatSerializationError(context, error) {
142
- // Use "returning" for return values, "passing" for arguments/inputs
143
- const verb = context.includes('return value') ? 'returning' : 'passing';
144
- // Build the error message with path info if available from DevalueError
145
- let message = `Failed to serialize ${context}`;
146
- if (error instanceof DevalueError && error.path) {
147
- message += ` at path "${error.path}"`;
148
- }
149
- message += `. Ensure you're ${verb} serializable types (plain objects, arrays, primitives, Date, RegExp, Map, Set).`;
150
- // Log the problematic value for debugging
151
- if (error instanceof DevalueError && error.value !== undefined) {
152
- runtimeLogger.error('Serialization failed', {
153
- context,
154
- problematicValue: error.value,
155
- });
156
- }
157
- return message;
158
- }
159
40
  /**
160
41
  * Detect if a readable stream is a byte stream.
161
42
  *
@@ -179,10 +60,72 @@ export function getStreamType(stream) {
179
60
  * split across transport reads.
180
61
  */
181
62
  const FRAME_HEADER_SIZE = 4;
63
+ /**
64
+ * The mode-specific serializers (`./serialization/{client,step,workflow}.ts`)
65
+ * already throw a `SerializationError` whose `.cause` is the underlying
66
+ * devalue / serde failure. The outer dehydrate/hydrate wrappers want to
67
+ * re-frame that error with a more specific context label (e.g. "workflow
68
+ * arguments" instead of generic "workflow value"), so they unwrap the
69
+ * inner SerializationError and reformat with the original cause. Errors
70
+ * that aren't already SerializationError flow through unchanged.
71
+ *
72
+ * `RuntimeDecryptionError` is an exception: it must keep its identity (and
73
+ * `context`) so the run-failure classifier routes it to `RUNTIME_ERROR`,
74
+ * so this rethrows it unchanged before any unwrapping. Note this guard
75
+ * must run before the generic `WorkflowRuntimeError` unwrap below, since
76
+ * `RuntimeDecryptionError` extends `WorkflowRuntimeError` and carries a
77
+ * `cause` (the underlying DOMException) that would otherwise be unwrapped
78
+ * and reframed as a `SerializationError`.
79
+ */
80
+ function unwrapSerializationCause(error) {
81
+ rethrowIfRuntimeError(error);
82
+ if (error instanceof SerializationError && error.cause !== undefined) {
83
+ return error.cause;
84
+ }
85
+ if (error instanceof WorkflowRuntimeError && error.cause !== undefined) {
86
+ return error.cause;
87
+ }
88
+ return error;
89
+ }
90
+ /**
91
+ * Emit compression telemetry onto the active span after a (de)serialize.
92
+ *
93
+ * The compression layer populates `stats` only when it actually ran (binary
94
+ * data on a spec >= 5 path); legacy / v1Compat paths leave it unrecorded, so
95
+ * this no-ops for them and avoids the `getActiveSpan` lookup. Attributes land
96
+ * on whatever span is active — typically the dedicated `step.dehydrate` /
97
+ * `step.hydrate` span, otherwise the enclosing run/start span.
98
+ */
99
+ async function recordCompression(stats, operation) {
100
+ if (!stats.recorded)
101
+ return;
102
+ // Telemetry must never break the serialize/deserialize data path — a
103
+ // missing/failing tracer is purely an observability loss.
104
+ try {
105
+ const span = await getActiveSpan();
106
+ if (!span)
107
+ return;
108
+ const uncompressedBytes = stats.uncompressedBytes ?? 0;
109
+ const storedBytes = stats.storedBytes ?? 0;
110
+ span.setAttributes({
111
+ ...Attr.SerializationOperation(operation),
112
+ ...Attr.SerializationCompressed(stats.compressed ?? false),
113
+ ...Attr.SerializationCodec(stats.codec ?? 'none'),
114
+ ...Attr.SerializationUncompressedBytes(uncompressedBytes),
115
+ ...Attr.SerializationStoredBytes(storedBytes),
116
+ ...(stats.compressed && uncompressedBytes > 0
117
+ ? Attr.SerializationCompressionRatio(1 - storedBytes / uncompressedBytes)
118
+ : {}),
119
+ });
120
+ }
121
+ catch {
122
+ // ignore telemetry failures
123
+ }
124
+ }
182
125
  export function getSerializeStream(reducers, cryptoKey) {
183
126
  const encoder = new TextEncoder();
184
- // Resolve the key promise once on first use and cache the result.
185
- // Note: if the cryptoKey promise rejects (e.g., network error fetching
127
+ // Resolve the key input once on first use and cache the result.
128
+ // Note: if resolving cryptoKey rejects (e.g., network error fetching
186
129
  // the derived key), the rejection won't surface until the first chunk
187
130
  // is processed — not at stream construction time.
188
131
  const keyState = { resolved: false, key: undefined };
@@ -190,7 +133,7 @@ export function getSerializeStream(reducers, cryptoKey) {
190
133
  async transform(chunk, controller) {
191
134
  try {
192
135
  if (!keyState.resolved) {
193
- keyState.key = await cryptoKey;
136
+ keyState.key = await resolveEncryptionKey(cryptoKey);
194
137
  keyState.resolved = true;
195
138
  }
196
139
  const serialized = stringify(chunk, reducers);
@@ -210,7 +153,15 @@ export function getSerializeStream(reducers, cryptoKey) {
210
153
  controller.enqueue(frame);
211
154
  }
212
155
  catch (error) {
213
- controller.error(new WorkflowRuntimeError(formatSerializationError('stream chunk', error), { slug: 'serialization-failed', cause: error }));
156
+ // Encryption failures must keep their RuntimeDecryptionError
157
+ // identity (RUNTIME_ERROR) rather than be reframed as a
158
+ // SerializationError (USER_ERROR).
159
+ if (RuntimeDecryptionError.is(error)) {
160
+ controller.error(error);
161
+ return;
162
+ }
163
+ const { message, hint } = formatSerializationError('stream chunk', error);
164
+ controller.error(new SerializationError(message, { hint, cause: error }));
214
165
  }
215
166
  },
216
167
  });
@@ -219,7 +170,7 @@ export function getSerializeStream(reducers, cryptoKey) {
219
170
  export function getDeserializeStream(revivers, cryptoKey) {
220
171
  const decoder = new TextDecoder();
221
172
  let buffer = new Uint8Array(0);
222
- // Resolve the key promise once on first use and cache the result.
173
+ // Resolve the key input once on first use and cache the result.
223
174
  const keyState = { resolved: false, key: undefined };
224
175
  function appendToBuffer(data) {
225
176
  const newBuffer = new Uint8Array(buffer.length + data.length);
@@ -228,9 +179,9 @@ export function getDeserializeStream(revivers, cryptoKey) {
228
179
  buffer = newBuffer;
229
180
  }
230
181
  async function processFrames(controller) {
231
- // Resolve the key promise once on first use and cache the result
182
+ // Resolve the key input once on first use and cache the result
232
183
  if (!keyState.resolved) {
233
- keyState.key = await cryptoKey;
184
+ keyState.key = await resolveEncryptionKey(cryptoKey);
234
185
  keyState.resolved = true;
235
186
  }
236
187
  // Try to extract complete length-prefixed frames
@@ -247,11 +198,30 @@ export function getDeserializeStream(revivers, cryptoKey) {
247
198
  // then fall through to the normal deserialization path.
248
199
  if (format === SerializationFormat.ENCRYPTED) {
249
200
  if (!keyState.key) {
250
- controller.error(new WorkflowRuntimeError('Encrypted stream data encountered but no encryption key is available. ' +
251
- 'Encryption is not configured or no key was provided for this run.'));
201
+ controller.error(new RuntimeDecryptionError('Encrypted stream data encountered but no encryption key is available. ' +
202
+ 'Encryption is not configured or no key was provided for this run.', {
203
+ context: {
204
+ operation: 'decrypt',
205
+ byteLength: payload.byteLength,
206
+ formatPrefix: 'encr',
207
+ },
208
+ }));
252
209
  return;
253
210
  }
254
- const decrypted = await aesGcmDecrypt(keyState.key, payload);
211
+ let decrypted;
212
+ try {
213
+ decrypted = await aesGcmDecrypt(keyState.key, payload);
214
+ }
215
+ catch (error) {
216
+ // The low-level AES layer only sees the stripped payload, so it
217
+ // cannot record the outer envelope prefix. We peeked it here
218
+ // (`encr`), so enrich the diagnostic context with the real format
219
+ // prefix before propagating — mirroring serialization/encryption.ts.
220
+ if (RuntimeDecryptionError.is(error) && error.context) {
221
+ error.context.formatPrefix = format;
222
+ }
223
+ throw error;
224
+ }
255
225
  ({ format, payload } = decodeFormatPrefix(decrypted));
256
226
  }
257
227
  if (format === SerializationFormat.DEVALUE_V1) {
@@ -299,11 +269,130 @@ export function getDeserializeStream(revivers, cryptoKey) {
299
269
  });
300
270
  return stream;
301
271
  }
272
+ // ============================================================================
273
+ // Byte-stream wire framing
274
+ // ============================================================================
275
+ //
276
+ // Byte streams (`type: 'bytes'` ReadableStreams passed across boundaries)
277
+ // are written to the underlying world's stream transport one user chunk at
278
+ // a time. Without an in-band envelope, the reader sees a flat stream of
279
+ // bytes — there is no way to tell where one user chunk ends and the next
280
+ // begins, which makes mid-stream reconnect impossible (we don't know how
281
+ // many server-side chunks have been consumed).
282
+ //
283
+ // To enable transparent reconnect, this PR introduces an opt-in wire
284
+ // envelope that wraps each user chunk in a length-prefix:
285
+ //
286
+ // [4-byte big-endian length][user payload bytes]
287
+ //
288
+ // The envelope is identical in shape to `getSerializeStream`'s framing,
289
+ // but the payload here is *raw user bytes* — there is no inner
290
+ // format-prefix, no devalue, no encryption. A framed byte stream stays
291
+ // semantically a byte stream end-to-end; the framing is purely transport.
292
+ //
293
+ // The decision to use framing for a given stream is recorded in the
294
+ // serialized stream ref (`framing: 'framed-v1'`), so both sides agree on
295
+ // the wire format without runtime negotiation. Producers that target a
296
+ // run whose deployment doesn't support framing (see `getRunCapabilities`
297
+ // in capabilities.ts) emit raw bytes and a ref without the field — which
298
+ // the reader treats as legacy raw bytes for backwards compatibility.
299
+ /**
300
+ * Maximum allowed byte-stream frame payload size (100MB). Shared by the
301
+ * framer (rejects oversized user chunks at write time, where the error is
302
+ * actionable) and the unframer (rejects oversized length headers at read
303
+ * time, which usually indicate a non-framed wire being read as framed).
304
+ * Keeping both sides on one constant guarantees any chunk the framer
305
+ * accepts can always be decoded by the unframer.
306
+ */
307
+ const MAX_FRAME_SIZE = 100_000_000;
308
+ /**
309
+ * Wraps each chunk of a byte stream in a 4-byte big-endian length
310
+ * prefix. Used by the producer side of a framed byte-stream pipe.
311
+ *
312
+ * Empty chunks (length 0) are dropped — the resulting `[0x00 0x00 0x00 0x00]`
313
+ * frame would be ambiguous with the legacy "looks framed" detection in
314
+ * `getDeserializeStream`, and it carries no information.
315
+ *
316
+ * Load-bearing invariant: each user chunk becomes exactly one frame, and
317
+ * each frame is enqueued as exactly one transport chunk (the downstream
318
+ * writable performs one wire write per chunk, preserving boundaries). The
319
+ * server therefore stores one frame per chunk index, which is what allows
320
+ * a future reconnecting reader to resume a framed byte stream at
321
+ * `startIndex + consumedFrames` — the same arithmetic
322
+ * `createReconnectingFramedStream` relies on for object streams. Do not
323
+ * coalesce or split frames here without revisiting that resume logic.
324
+ */
325
+ export function getByteFramingStream() {
326
+ return new TransformStream({
327
+ transform(chunk, controller) {
328
+ if (chunk.length === 0)
329
+ return;
330
+ if (chunk.length > MAX_FRAME_SIZE) {
331
+ controller.error(new WorkflowRuntimeError(`Byte-stream chunk of ${chunk.length} bytes exceeds the maximum ` +
332
+ `framed chunk size (${MAX_FRAME_SIZE}). Split the data into ` +
333
+ `smaller chunks before writing.`, { slug: 'serialization-failed' }));
334
+ return;
335
+ }
336
+ const frame = new Uint8Array(FRAME_HEADER_SIZE + chunk.length);
337
+ new DataView(frame.buffer).setUint32(0, chunk.length, false);
338
+ frame.set(chunk, FRAME_HEADER_SIZE);
339
+ controller.enqueue(frame);
340
+ },
341
+ });
342
+ }
343
+ /**
344
+ * Unwraps length-prefixed byte-stream frames back into the original user
345
+ * chunks. Used by the consumer side of a framed byte-stream pipe.
346
+ *
347
+ * Buffers across read boundaries — the transport may split a single
348
+ * frame across multiple reads (header in one chunk, payload in another)
349
+ * or coalesce multiple frames into a single read. The transform emits
350
+ * whole user chunks regardless of transport chunking.
351
+ *
352
+ * Errors the stream if the length header advertises a frame larger than
353
+ * `MAX_FRAME_SIZE` bytes, since that almost certainly indicates a
354
+ * misframed wire (e.g. a raw byte stream being fed through this transform
355
+ * by mistake) and we don't want to allocate an enormous buffer.
356
+ */
357
+ export function getByteUnframingStream() {
358
+ let buffer = new Uint8Array(0);
359
+ function appendToBuffer(data) {
360
+ const next = new Uint8Array(buffer.length + data.length);
361
+ next.set(buffer, 0);
362
+ next.set(data, buffer.length);
363
+ buffer = next;
364
+ }
365
+ return new TransformStream({
366
+ transform(chunk, controller) {
367
+ if (chunk.length > 0)
368
+ appendToBuffer(chunk);
369
+ while (buffer.length >= FRAME_HEADER_SIZE) {
370
+ const frameLength = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength).getUint32(0, false);
371
+ if (frameLength > MAX_FRAME_SIZE) {
372
+ controller.error(new WorkflowRuntimeError(`Byte-stream frame length ${frameLength} exceeds maximum (${MAX_FRAME_SIZE}). ` +
373
+ `This usually means a non-framed byte stream is being read as framed.`, { slug: 'serialization-failed' }));
374
+ return;
375
+ }
376
+ const total = FRAME_HEADER_SIZE + frameLength;
377
+ if (buffer.length < total)
378
+ break;
379
+ controller.enqueue(buffer.slice(FRAME_HEADER_SIZE, total));
380
+ buffer = buffer.slice(total);
381
+ }
382
+ },
383
+ flush(controller) {
384
+ if (buffer.length > 0) {
385
+ controller.error(new WorkflowRuntimeError(`Byte-stream ended with ${buffer.length} bytes of incomplete frame data. ` +
386
+ `The stream was truncated mid-frame.`, { slug: 'serialization-failed' }));
387
+ }
388
+ },
389
+ });
390
+ }
302
391
  export class WorkflowServerReadableStream extends ReadableStream {
303
392
  #reader;
304
393
  constructor(runId, name, startIndex) {
305
394
  if (typeof name !== 'string' || name.length === 0) {
306
- throw new Error(`"name" is required, got "${name}"`);
395
+ throw new WorkflowRuntimeError(`"name" is required, got "${name}"`);
307
396
  }
308
397
  super({
309
398
  // @ts-expect-error Not sure why TypeScript is complaining about this
@@ -311,7 +400,7 @@ export class WorkflowServerReadableStream extends ReadableStream {
311
400
  pull: async (controller) => {
312
401
  let reader = this.#reader;
313
402
  if (!reader) {
314
- const world = await getWorld();
403
+ const world = await getWorldLazy();
315
404
  const stream = await world.streams.get(runId, name, startIndex);
316
405
  reader = this.#reader = stream.getReader();
317
406
  }
@@ -339,6 +428,163 @@ export class WorkflowServerReadableStream extends ReadableStream {
339
428
  });
340
429
  }
341
430
  }
431
+ /**
432
+ * Maximum consecutive reconnect attempts for a single framed stream session.
433
+ * The counter resets to zero whenever a reconnect makes forward progress (a
434
+ * frame is delivered), so this bounds *consecutive* failures, not the lifetime
435
+ * total — a long-lived serverless stream may legitimately reconnect far more
436
+ * than this many times as long as each reconnect keeps delivering data. We only
437
+ * give up after this many reconnects in a row produce nothing.
438
+ */
439
+ export const FRAMED_STREAM_MAX_RECONNECTS = 50;
440
+ /**
441
+ * Absolute backstop on total reconnects for a single session, independent of
442
+ * progress. The consecutive cap above resets on forward progress, which is
443
+ * correct for a well-behaved backend that honors `startIndex`. But if a World's
444
+ * `streams.get` ever ignored `startIndex` and re-delivered earlier chunks,
445
+ * "progress" would be reported every reconnect and the consecutive cap would
446
+ * never trip — turning a bounded failure into an unbounded reconnect loop. This
447
+ * hard ceiling guarantees the loop always terminates. It is set high enough
448
+ * (hours of streaming at realistic per-session timeouts) to never interfere
449
+ * with legitimate long-lived streams.
450
+ */
451
+ export const FRAMED_STREAM_MAX_TOTAL_RECONNECTS = 1000;
452
+ /**
453
+ * Wraps the length-prefix-framed byte stream from `world.streams.get` with
454
+ * transparent auto-reconnect.
455
+ *
456
+ * Every fully-decoded outer frame corresponds to exactly one server-side
457
+ * chunk (the serialize transform enqueues one frame per workflow write, and
458
+ * the writable buffers one frame per chunk when multi-writing). The wrapper
459
+ * counts completed frames and, on upstream error, reopens the connection
460
+ * with `startIndex = resolvedStartIndex + consumedFrames`. Partial-frame
461
+ * bytes buffered before the cut are discarded — the server will resend the
462
+ * in-flight chunk in full from the new startIndex.
463
+ *
464
+ * A clean upstream close (EOF with no error) signals the stream is truly
465
+ * done; we close the wrapper and do not reconnect.
466
+ *
467
+ * Negative `startIndex` values (last-N semantics) skip the reconnect
468
+ * machinery because we cannot compute an absolute resume position without
469
+ * a tail-index lookup — the returned stream behaves as a single-shot read.
470
+ */
471
+ export function createReconnectingFramedStream(runId, name, startIndex) {
472
+ const reconnectSupported = startIndex === undefined || startIndex >= 0;
473
+ let currentStartIndex = startIndex ?? 0;
474
+ let consumedFrames = 0;
475
+ let reconnectCount = 0;
476
+ let totalReconnectCount = 0;
477
+ let reader;
478
+ let buffer = new Uint8Array(0);
479
+ async function connect() {
480
+ const world = await getWorldLazy();
481
+ const effectiveStartIndex = reconnectSupported
482
+ ? currentStartIndex + consumedFrames
483
+ : startIndex;
484
+ const stream = await world.streams.get(runId, name, effectiveStartIndex);
485
+ reader = stream.getReader();
486
+ }
487
+ async function reconnect() {
488
+ reconnectCount++;
489
+ totalReconnectCount++;
490
+ if (reconnectCount > FRAMED_STREAM_MAX_RECONNECTS) {
491
+ throw new Error(`Stream "${name}" exceeded maximum reconnection attempts (${FRAMED_STREAM_MAX_RECONNECTS})`);
492
+ }
493
+ if (totalReconnectCount > FRAMED_STREAM_MAX_TOTAL_RECONNECTS) {
494
+ throw new Error(`Stream "${name}" exceeded maximum total reconnection attempts (${FRAMED_STREAM_MAX_TOTAL_RECONNECTS})`);
495
+ }
496
+ if (reader) {
497
+ await reader.cancel().catch(() => { });
498
+ reader = undefined;
499
+ }
500
+ currentStartIndex += consumedFrames;
501
+ consumedFrames = 0;
502
+ buffer = new Uint8Array(0);
503
+ await connect();
504
+ }
505
+ return new ReadableStream({
506
+ pull: async (controller) => {
507
+ // Loop until we emit something, hit EOF, or fatally error. Reads that
508
+ // only extend the in-flight-frame buffer don't enqueue anything — we
509
+ // keep reading rather than returning empty-handed.
510
+ for (;;) {
511
+ if (!reader) {
512
+ try {
513
+ await connect();
514
+ }
515
+ catch (err) {
516
+ controller.error(err);
517
+ return;
518
+ }
519
+ }
520
+ let result;
521
+ try {
522
+ // biome-ignore lint/style/noNonNullAssertion: connect() guarantees reader
523
+ result = await reader.read();
524
+ }
525
+ catch (err) {
526
+ if (!reconnectSupported) {
527
+ controller.error(err);
528
+ return;
529
+ }
530
+ try {
531
+ await reconnect();
532
+ }
533
+ catch (reconnectErr) {
534
+ controller.error(reconnectErr);
535
+ return;
536
+ }
537
+ continue;
538
+ }
539
+ if (result.done || !result.value) {
540
+ // Clean EOF — stream is truly complete. Drop any partial-frame
541
+ // bytes (there shouldn't be any; a well-formed stream ends on a
542
+ // frame boundary).
543
+ reader = undefined;
544
+ controller.close();
545
+ return;
546
+ }
547
+ // Append to buffer and emit all complete frames.
548
+ const incoming = result.value;
549
+ if (incoming.length > 0) {
550
+ const combined = new Uint8Array(buffer.length + incoming.length);
551
+ combined.set(buffer, 0);
552
+ combined.set(incoming, buffer.length);
553
+ buffer = combined;
554
+ }
555
+ let emitted = false;
556
+ while (buffer.length >= FRAME_HEADER_SIZE) {
557
+ const frameLength = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength).getUint32(0, false);
558
+ const total = FRAME_HEADER_SIZE + frameLength;
559
+ if (buffer.length < total)
560
+ break;
561
+ // Forward the entire framed chunk (header + payload) to the
562
+ // downstream deserializer, which already expects this layout.
563
+ controller.enqueue(buffer.slice(0, total));
564
+ buffer = buffer.slice(total);
565
+ consumedFrames++;
566
+ emitted = true;
567
+ }
568
+ if (emitted) {
569
+ // Forward progress on the current connection — clear the
570
+ // consecutive-failure budget so a long stream that reconnects
571
+ // many times (but keeps delivering) is never falsely capped.
572
+ reconnectCount = 0;
573
+ return;
574
+ }
575
+ // Only partial bytes — read more.
576
+ }
577
+ },
578
+ cancel: async () => {
579
+ if (reader) {
580
+ await reader.cancel().catch((err) => {
581
+ console.warn('Error closing ReadableStream reader:', err);
582
+ });
583
+ reader = undefined;
584
+ }
585
+ },
586
+ });
587
+ }
342
588
  /**
343
589
  * Default flush interval in milliseconds for buffered stream writes.
344
590
  * Chunks are accumulated and flushed together to reduce network overhead.
@@ -347,12 +593,12 @@ const STREAM_FLUSH_INTERVAL_MS = 10;
347
593
  export class WorkflowServerWritableStream extends WritableStream {
348
594
  constructor(runId, name) {
349
595
  if (typeof runId !== 'string') {
350
- throw new Error(`"runId" must be a string, got "${typeof runId}"`);
596
+ throw new WorkflowRuntimeError(`"runId" must be a string, got "${typeof runId}"`);
351
597
  }
352
598
  if (typeof name !== 'string' || name.length === 0) {
353
- throw new Error(`"name" is required, got "${name}"`);
599
+ throw new WorkflowRuntimeError(`"name" is required, got "${name}"`);
354
600
  }
355
- const worldPromise = getWorld();
601
+ const worldPromise = getWorldLazy();
356
602
  // Buffering state for batched writes
357
603
  // Encryption/decryption is handled at the framing level by
358
604
  // getSerializeStream/getDeserializeStream, not here.
@@ -457,113 +703,22 @@ export class WorkflowServerWritableStream extends WritableStream {
457
703
  });
458
704
  }
459
705
  }
460
- function revive(str) {
461
- // biome-ignore lint/security/noGlobalEval: Eval is safe here - we are only passing value from `devalue.stringify()`
462
- // biome-ignore lint/complexity/noCommaOperator: This is how you do global scope eval
463
- return (0, eval)(`(${str})`);
464
- }
465
- function getCommonReducers(global = globalThis) {
466
- const abToBase64 = (value, offset, length) => {
467
- // Avoid returning falsy value for zero-length buffers
468
- if (length === 0)
469
- return '.';
470
- // Create a proper copy to avoid ArrayBuffer detachment issues
471
- // Buffer.from(ArrayBuffer, offset, length) creates a view, not a copy
472
- const uint8 = new Uint8Array(value, offset, length);
473
- return Buffer.from(uint8).toString('base64');
474
- };
475
- const viewToBase64 = (value) => abToBase64(value.buffer, value.byteOffset, value.byteLength);
706
+ // ---- Composed reducers ----
707
+ // Composes modular reducers (common, class, step-function) with
708
+ // mode-specific Request/Response/Stream reducers below.
709
+ /**
710
+ * Base reducers shared across all serialization boundaries.
711
+ * Composes: class + step-function + common reducers from the modular modules.
712
+ */
713
+ function getAllBaseReducers(global = globalThis) {
714
+ // Class/Instance MUST come before Error so that custom Error subclasses
715
+ // with WORKFLOW_SERIALIZE take precedence (devalue uses first-match-wins).
476
716
  return {
477
- ArrayBuffer: (value) => value instanceof global.ArrayBuffer &&
478
- abToBase64(value, 0, value.byteLength),
479
- BigInt: (value) => typeof value === 'bigint' && value.toString(),
480
- BigInt64Array: (value) => value instanceof global.BigInt64Array && viewToBase64(value),
481
- BigUint64Array: (value) => value instanceof global.BigUint64Array && viewToBase64(value),
482
- // Class and Instance are intentionally placed before Error so that
483
- // custom Error subclasses with WORKFLOW_SERIALIZE take precedence
484
- // over the generic Error serialization (devalue uses first-match-wins).
485
- Class: (value) => {
486
- // Check if this is a class constructor with a classId property
487
- // (set by the SWC plugin for classes with static step/workflow methods)
488
- if (typeof value !== 'function')
489
- return false;
490
- const classId = value.classId;
491
- if (typeof classId !== 'string')
492
- return false;
493
- return { classId };
494
- },
495
- Instance: (value) => {
496
- // Check if this is an instance of a class with custom serialization
497
- if (value === null || typeof value !== 'object')
498
- return false;
499
- const cls = value.constructor;
500
- if (!cls || typeof cls !== 'function')
501
- return false;
502
- // Check if the class has a static WORKFLOW_SERIALIZE method
503
- const serialize = cls[WORKFLOW_SERIALIZE];
504
- if (typeof serialize !== 'function') {
505
- return false;
506
- }
507
- // Get the classId from the static class property (set by SWC plugin)
508
- const classId = cls.classId;
509
- if (typeof classId !== 'string') {
510
- throw new Error(`Class "${cls.name}" with ${String(WORKFLOW_SERIALIZE)} must have a static "classId" property.`);
511
- }
512
- // Serialize the instance using the custom serializer
513
- const data = serialize.call(cls, value);
514
- return { classId, data };
515
- },
516
- Date: (value) => {
517
- if (!(value instanceof global.Date))
518
- return false;
519
- const valid = !Number.isNaN(value.getDate());
520
- // Note: "." is to avoid returning a falsy value when the date is invalid
521
- return valid ? value.toISOString() : '.';
522
- },
523
- // DOMException is a special case: in Node.js it passes isNativeError()
524
- // and instanceof Error, but has a unique constructor signature
525
- // (message, name) and a read-only numeric `code` property derived from
526
- // `name`. It must be checked before the generic Error reducer.
527
- DOMException: (value) => {
528
- if (!types.isNativeError(value))
529
- return false;
530
- if (value.constructor?.name !== 'DOMException')
531
- return false;
532
- const reduced = {
533
- message: value.message,
534
- name: value.name,
535
- stack: value.stack,
536
- };
537
- if ('cause' in value)
538
- reduced.cause = value.cause;
539
- return reduced;
540
- },
541
- Error: (value) => {
542
- // Use types.isNativeError() instead of `instanceof global.Error`
543
- // because errors may originate from a different VM context (e.g.
544
- // FatalError from the host context passed into a VM-context workflow).
545
- // `instanceof` checks fail across VM boundaries since each context
546
- // has its own Error constructor, but isNativeError() uses V8's
547
- // internal type tag which works across all contexts.
548
- if (!types.isNativeError(value))
549
- return false;
550
- return {
551
- name: value.name,
552
- message: value.message,
553
- stack: value.stack,
554
- };
555
- },
556
- Float32Array: (value) => value instanceof global.Float32Array && viewToBase64(value),
557
- Float64Array: (value) => value instanceof global.Float64Array && viewToBase64(value),
558
- Headers: (value) => value instanceof global.Headers && Array.from(value),
559
- Int8Array: (value) => value instanceof global.Int8Array && viewToBase64(value),
560
- Int16Array: (value) => value instanceof global.Int16Array && viewToBase64(value),
561
- Int32Array: (value) => value instanceof global.Int32Array && viewToBase64(value),
562
- Map: (value) => value instanceof global.Map && Array.from(value),
563
- RegExp: (value) => value instanceof global.RegExp && {
564
- source: value.source,
565
- flags: value.flags,
566
- },
717
+ ...getClassReducers(),
718
+ ...getStepFunctionReducer(),
719
+ ...getCommonReducers(global),
720
+ // Request and Response reducers are mode-specific and added by
721
+ // getExternalReducers / getWorkflowReducers / getStepReducers below.
567
722
  Request: (value) => {
568
723
  if (!(value instanceof global.Request))
569
724
  return false;
@@ -578,6 +733,20 @@ function getCommonReducers(global = globalThis) {
578
733
  if (responseWritable) {
579
734
  data.responseWritable = responseWritable;
580
735
  }
736
+ // Forward the signal in two cases:
737
+ // 1. Already aborted — preserve aborted=true/reason so the hydrated
738
+ // step sees the cancellation that happened before serialize.
739
+ // 2. Already tagged with workflow infrastructure — i.e. a signal
740
+ // from a workflow-managed AbortController, which has stream/hook
741
+ // backing for cross-boundary propagation.
742
+ // Plain non-aborted native signals are intentionally dropped (would
743
+ // mint stream infra for every Request, including the auto-generated
744
+ // signal on `new Request(url)`).
745
+ if (value.signal &&
746
+ (value.signal.aborted ||
747
+ value.signal[ABORT_STREAM_NAME])) {
748
+ data.signal = value.signal;
749
+ }
581
750
  return data;
582
751
  },
583
752
  Response: (value) => {
@@ -593,94 +762,186 @@ function getCommonReducers(global = globalThis) {
593
762
  redirected: value.redirected,
594
763
  };
595
764
  },
596
- Set: (value) => value instanceof global.Set && Array.from(value),
597
- StepFunction: (value) => {
598
- if (typeof value !== 'function')
599
- return false;
600
- const stepId = value.stepId;
601
- if (typeof stepId !== 'string')
602
- return false;
603
- // Check if the step function has closure variables
604
- const closureVarsFn = value.__closureVarsFn;
605
- if (closureVarsFn && typeof closureVarsFn === 'function') {
606
- // Invoke the closure variables function and serialize along with stepId
607
- const closureVars = closureVarsFn();
608
- return { stepId, closureVars };
609
- }
610
- // No closure variables - return object with just stepId
611
- return { stepId };
612
- },
613
- URL: (value) => value instanceof global.URL && value.href,
614
- WorkflowFunction: (value) => {
615
- // Only match function references with a workflowId property (set by
616
- // the SWC compiler on workflow functions). Plain { workflowId } objects
617
- // are NOT matched — this prevents infinite recursion since the reduced
618
- // form { workflowId } is a plain object, not a function.
619
- if (typeof value !== 'function')
620
- return false;
621
- const workflowId = value.workflowId;
622
- if (typeof workflowId !== 'string')
623
- return false;
624
- return { workflowId };
625
- },
626
- URLSearchParams: (value) => {
627
- if (!(value instanceof global.URLSearchParams))
628
- return false;
629
- // Avoid returning a falsy value when the URLSearchParams is empty
630
- if (value.size === 0)
631
- return '.';
632
- return String(value);
633
- },
634
- Uint8Array: (value) => value instanceof global.Uint8Array && viewToBase64(value),
635
- Uint8ClampedArray: (value) => value instanceof global.Uint8ClampedArray && viewToBase64(value),
636
- Uint16Array: (value) => value instanceof global.Uint16Array && viewToBase64(value),
637
- Uint32Array: (value) => value instanceof global.Uint32Array && viewToBase64(value),
638
765
  };
639
766
  }
767
+ /**
768
+ * Shared logic for AbortController/AbortSignal reducers in external and step
769
+ * contexts. Assigns stream/hook names if not already present, optionally
770
+ * attaches an abort listener for real-time propagation, and returns the
771
+ * serialized representation.
772
+ */
773
+ function reduceAbortWithListener(signal, holder, global, ops, runId, cryptoKey) {
774
+ let streamName = holder[ABORT_STREAM_NAME];
775
+ let hookToken = holder[ABORT_HOOK_TOKEN];
776
+ if (!streamName) {
777
+ const id = (global[STABLE_ULID] || defaultUlid)();
778
+ streamName = getAbortStreamId(id);
779
+ hookToken = `abrt_${id}`;
780
+ holder[ABORT_STREAM_NAME] = streamName;
781
+ holder[ABORT_HOOK_TOKEN] = hookToken;
782
+ if (holder.signal) {
783
+ holder.signal[ABORT_STREAM_NAME] = streamName;
784
+ holder.signal[ABORT_HOOK_TOKEN] = hookToken;
785
+ }
786
+ }
787
+ // Deduped via ABORT_LISTENER_ATTACHED marker — see attachAbortListenerOnce.
788
+ attachAbortListenerOnce(signal, streamName, runId, cryptoKey, ops);
789
+ return {
790
+ streamName,
791
+ hookToken: hookToken,
792
+ aborted: signal.aborted,
793
+ reason: signal.aborted ? signal.reason : undefined,
794
+ };
795
+ }
796
+ /**
797
+ * Shared logic for AbortController/AbortSignal reducers in workflow context.
798
+ * Reads existing stream/hook names from symbols (must already be set).
799
+ */
800
+ function reduceAbortBySymbol(signal, holder) {
801
+ const streamName = holder[ABORT_STREAM_NAME] ?? holder.signal?.[ABORT_STREAM_NAME];
802
+ const hookToken = holder[ABORT_HOOK_TOKEN] ?? holder.signal?.[ABORT_HOOK_TOKEN];
803
+ if (!streamName) {
804
+ throw new Error('AbortController/AbortSignal stream name is not set');
805
+ }
806
+ return {
807
+ streamName,
808
+ hookToken: hookToken,
809
+ aborted: signal.aborted,
810
+ reason: signal.aborted ? signal.reason : undefined,
811
+ };
812
+ }
813
+ /**
814
+ * Attach a single abort listener to a signal, deduped across calls.
815
+ *
816
+ * Each serialization pass goes through the reducer, but a controller passed
817
+ * to N steps would otherwise accumulate N listeners — each writing the same
818
+ * stream packet and double-closing the stream on abort. The marker symbol
819
+ * ensures the stream-write side-effect runs at most once per (signal, runId).
820
+ */
821
+ function attachAbortListenerOnce(signal, streamName, runId, cryptoKey, ops) {
822
+ if (signal.aborted)
823
+ return;
824
+ if (signal[ABORT_LISTENER_ATTACHED])
825
+ return;
826
+ signal[ABORT_LISTENER_ATTACHED] = true;
827
+ signal.addEventListener('abort', () => {
828
+ ops.push((async () => {
829
+ try {
830
+ // Dehydrate via the same machinery the reader uses (hydrateStepArguments)
831
+ // so the reason round-trips with full type fidelity (DOMException,
832
+ // Errors, custom classes, etc.) and respects the run's encryption key.
833
+ // A bare JSON.stringify here would write a packet the reader can't
834
+ // decode and the listener-side abort would propagate with no reason.
835
+ const key = await resolveEncryptionKey(cryptoKey);
836
+ const payload = await dehydrateStepArguments({ aborted: true, reason: signal.reason }, runId, key);
837
+ const writable = new WorkflowServerWritableStream(runId, streamName);
838
+ const writer = writable.getWriter();
839
+ await writer.write(payload);
840
+ await writer.close();
841
+ }
842
+ catch {
843
+ // Best-effort stream write
844
+ }
845
+ })());
846
+ }, { once: true });
847
+ }
640
848
  /**
641
849
  * Reducers for serialization boundary from the client side, passing arguments
642
850
  * to the workflow handler.
643
851
  *
644
852
  * @param global
645
853
  * @param ops
854
+ * @param runId
855
+ * @param cryptoKey
856
+ * @param framedByteStreams - When `true`, byte streams (`type: 'bytes'`)
857
+ * are wrapped in length-prefixed frames on the wire so the consumer
858
+ * can reconnect on transient errors. Should match the target run's
859
+ * capability — see `getRunCapabilities` in `capabilities.ts`. Defaults
860
+ * to `false` for backwards compatibility with older runs.
646
861
  * @returns
647
862
  */
648
- export function getExternalReducers(global = globalThis, ops, runId, cryptoKey) {
863
+ export function getExternalReducers(global = globalThis, ops, runId, cryptoKey, framedByteStreams = false) {
649
864
  return {
650
- ...getCommonReducers(global),
865
+ ...getAllBaseReducers(global),
651
866
  ReadableStream: (value) => {
652
867
  if (!(value instanceof global.ReadableStream))
653
868
  return false;
654
869
  // Stream must not be locked when passing across execution boundary
655
870
  if (value.locked) {
656
- throw new Error('ReadableStream is locked');
871
+ throw new SerializationError('ReadableStream is locked and cannot be passed across a workflow boundary.', {
872
+ hint: 'Pass the stream before calling .getReader() / .pipeThrough() / .pipeTo(), or tee it with .tee() and pass one of the branches.',
873
+ });
657
874
  }
658
875
  const streamId = (global[STABLE_ULID] || defaultUlid)();
659
876
  const name = `strm_${streamId}`;
660
877
  const type = getStreamType(value);
661
878
  const writable = new WorkflowServerWritableStream(runId, name);
662
879
  if (type === 'bytes') {
663
- ops.push(value.pipeTo(writable));
880
+ if (framedByteStreams) {
881
+ ops.push(value.pipeThrough(getByteFramingStream()).pipeTo(writable));
882
+ }
883
+ else {
884
+ ops.push(value.pipeTo(writable));
885
+ }
664
886
  }
665
887
  else {
666
888
  ops.push(value
667
- .pipeThrough(getSerializeStream(getExternalReducers(global, ops, runId, cryptoKey), cryptoKey))
889
+ .pipeThrough(getSerializeStream(getExternalReducers(global, ops, runId, cryptoKey, framedByteStreams), cryptoKey))
668
890
  .pipeTo(writable));
669
891
  }
670
892
  const s = { name };
671
893
  if (type)
672
894
  s.type = type;
895
+ if (type === 'bytes' && framedByteStreams)
896
+ s.framing = 'framed-v1';
673
897
  return s;
674
898
  },
675
899
  WritableStream: (value) => {
676
900
  if (!(value instanceof global.WritableStream))
677
901
  return false;
902
+ // Fast path: when the writable is already backed by a workflow
903
+ // server stream (e.g. it came from a step-context `getWritable()`
904
+ // or was hydrated from a workflow input by `getStepRevivers`),
905
+ // forward its underlying `(runId, name)` to the receiving run.
906
+ // The receiving run's step-side reviver opens a server writable
907
+ // against the original `(runId, name)` and resolves that run's
908
+ // encryption key directly, so writes land on the original stream
909
+ // for the full lifetime of the receiving run — no in-process
910
+ // bridge tied to the dehydrating step's lifetime.
911
+ const existingName = value[STREAM_NAME_SYMBOL];
912
+ const existingRunId = value[STREAM_SERVER_RUN_ID_SYMBOL];
913
+ if (typeof existingName === 'string' &&
914
+ typeof existingRunId === 'string') {
915
+ const descriptor = {
916
+ name: existingName,
917
+ runId: existingRunId,
918
+ };
919
+ const existingDeploymentId = value[STREAM_SERVER_DEPLOYMENT_ID_SYMBOL];
920
+ if (typeof existingDeploymentId === 'string') {
921
+ descriptor.deploymentId = existingDeploymentId;
922
+ }
923
+ return descriptor;
924
+ }
678
925
  const streamId = (global[STABLE_ULID] || defaultUlid)();
679
926
  const name = `strm_${streamId}`;
680
927
  const readable = new WorkflowServerReadableStream(runId, name);
681
928
  ops.push(readable.pipeTo(value));
682
929
  return { name };
683
930
  },
931
+ AbortController: (value) => {
932
+ if (!global.AbortController ||
933
+ typeof global.AbortController !== 'function' ||
934
+ !(value instanceof global.AbortController))
935
+ return false;
936
+ return reduceAbortWithListener(value.signal, value, global, ops, runId, cryptoKey);
937
+ },
938
+ AbortSignal: (value) => {
939
+ if (!global.AbortSignal ||
940
+ typeof global.AbortSignal !== 'function' ||
941
+ !(value instanceof global.AbortSignal))
942
+ return false;
943
+ return reduceAbortWithListener(value, value, global, ops, runId, cryptoKey);
944
+ },
684
945
  };
685
946
  }
686
947
  /**
@@ -692,7 +953,7 @@ export function getExternalReducers(global = globalThis, ops, runId, cryptoKey)
692
953
  */
693
954
  export function getWorkflowReducers(global = globalThis) {
694
955
  return {
695
- ...getCommonReducers(global),
956
+ ...getAllBaseReducers(global),
696
957
  // Readable/Writable streams from within the workflow execution environment
697
958
  // are simply "handles" that can be passed around to other steps.
698
959
  ReadableStream: (value) => {
@@ -707,12 +968,15 @@ export function getWorkflowReducers(global = globalThis) {
707
968
  }
708
969
  const name = value[STREAM_NAME_SYMBOL];
709
970
  if (!name) {
710
- throw new Error('ReadableStream `name` is not set');
971
+ throw new WorkflowRuntimeError('ReadableStream `name` is not set');
711
972
  }
712
973
  const s = { name };
713
974
  const type = value[STREAM_TYPE_SYMBOL];
714
975
  if (type)
715
976
  s.type = type;
977
+ const framing = value[STREAM_FRAMING_SYMBOL];
978
+ if (framing)
979
+ s.framing = framing;
716
980
  return s;
717
981
  },
718
982
  WritableStream: (value) => {
@@ -720,9 +984,46 @@ export function getWorkflowReducers(global = globalThis) {
720
984
  return false;
721
985
  const name = value[STREAM_NAME_SYMBOL];
722
986
  if (!name) {
723
- throw new Error('WritableStream `name` is not set');
987
+ throw new WorkflowRuntimeError('WritableStream `name` is not set');
724
988
  }
725
- return { name };
989
+ const s = { name };
990
+ // When the handle was forwarded from another run (parent → child
991
+ // via `start()`), preserve the foreign runId so the step-side
992
+ // reviver opens the writable against the original stream.
993
+ const foreignRunId = value[STREAM_SERVER_RUN_ID_SYMBOL];
994
+ if (typeof foreignRunId === 'string')
995
+ s.runId = foreignRunId;
996
+ const foreignDeploymentId = value[STREAM_SERVER_DEPLOYMENT_ID_SYMBOL];
997
+ if (typeof foreignDeploymentId === 'string') {
998
+ s.deploymentId = foreignDeploymentId;
999
+ }
1000
+ return s;
1001
+ },
1002
+ // AbortController/AbortSignal in workflow context — just read symbols (handles).
1003
+ // In the workflow VM, global.AbortController is a class but global.AbortSignal
1004
+ // is a plain object (not a class), so instanceof checks won't work for signals.
1005
+ // Detect instances by the presence of the ABORT_STREAM_NAME symbol instead.
1006
+ AbortController: (value) => {
1007
+ if (!value || !value.signal)
1008
+ return false;
1009
+ const holder = value;
1010
+ const hasAbortSymbol = holder[ABORT_STREAM_NAME] ?? holder.signal?.[ABORT_STREAM_NAME];
1011
+ const isNativeAbortController = global.AbortController &&
1012
+ typeof global.AbortController === 'function' &&
1013
+ value instanceof global.AbortController;
1014
+ if (!hasAbortSymbol && !isNativeAbortController)
1015
+ return false;
1016
+ return reduceAbortBySymbol(value.signal, holder);
1017
+ },
1018
+ AbortSignal: (value) => {
1019
+ const signal = value;
1020
+ const hasAbortSymbol = signal?.[ABORT_STREAM_NAME];
1021
+ const isNativeAbortSignal = global.AbortSignal &&
1022
+ typeof global.AbortSignal === 'function' &&
1023
+ value instanceof global.AbortSignal;
1024
+ if (!hasAbortSymbol && !isNativeAbortSignal)
1025
+ return false;
1026
+ return reduceAbortBySymbol(value, value);
726
1027
  },
727
1028
  };
728
1029
  }
@@ -735,44 +1036,61 @@ export function getWorkflowReducers(global = globalThis) {
735
1036
  * @param runId
736
1037
  * @returns
737
1038
  */
738
- function getStepReducers(global = globalThis, ops, runId, cryptoKey) {
1039
+ function getStepReducers(global = globalThis, ops, runId, cryptoKey, framedByteStreams = false) {
739
1040
  return {
740
- ...getCommonReducers(global),
1041
+ ...getAllBaseReducers(global),
741
1042
  ReadableStream: (value) => {
742
1043
  if (!(value instanceof global.ReadableStream))
743
1044
  return false;
744
1045
  // Stream must not be locked when passing across execution boundary
745
1046
  if (value.locked) {
746
- throw new Error('ReadableStream is locked');
1047
+ throw new SerializationError('ReadableStream is locked and cannot be passed across a workflow boundary.', {
1048
+ hint: 'Pass the stream before calling .getReader() / .pipeThrough() / .pipeTo(), or tee it with .tee() and pass one of the branches.',
1049
+ });
747
1050
  }
748
1051
  // Check if the stream already has the name symbol set, in which case
749
1052
  // it's already being sunk to the server and we can just return the
750
1053
  // name and type.
751
1054
  let name = value[STREAM_NAME_SYMBOL];
752
1055
  let type = value[STREAM_TYPE_SYMBOL];
1056
+ // The framing symbol is set when a workflow VM revives a stream
1057
+ // handle from a previous step (see `getWorkflowRevivers`). When
1058
+ // present we must propagate the same framing choice on the way
1059
+ // back out, since the bytes already on the server's stream are in
1060
+ // that format — switching format mid-stream would corrupt them.
1061
+ let framing = value[STREAM_FRAMING_SYMBOL];
753
1062
  if (!name) {
754
1063
  const streamId = (global[STABLE_ULID] || defaultUlid)();
755
1064
  name = `strm_${streamId}`;
756
1065
  type = getStreamType(value);
1066
+ framing = type === 'bytes' && framedByteStreams ? 'framed-v1' : framing;
757
1067
  const writable = new WorkflowServerWritableStream(runId, name);
758
1068
  if (type === 'bytes') {
759
- ops.push(value.pipeTo(writable));
1069
+ if (framing === 'framed-v1') {
1070
+ ops.push(value.pipeThrough(getByteFramingStream()).pipeTo(writable));
1071
+ }
1072
+ else {
1073
+ ops.push(value.pipeTo(writable));
1074
+ }
760
1075
  }
761
1076
  else {
762
1077
  ops.push(value
763
- .pipeThrough(getSerializeStream(getStepReducers(global, ops, runId, cryptoKey), cryptoKey))
1078
+ .pipeThrough(getSerializeStream(getStepReducers(global, ops, runId, cryptoKey, framedByteStreams), cryptoKey))
764
1079
  .pipeTo(writable));
765
1080
  }
766
1081
  }
767
1082
  const s = { name };
768
1083
  if (type)
769
1084
  s.type = type;
1085
+ if (framing)
1086
+ s.framing = framing;
770
1087
  return s;
771
1088
  },
772
1089
  WritableStream: (value) => {
773
1090
  if (!(value instanceof global.WritableStream))
774
1091
  return false;
775
1092
  let name = value[STREAM_NAME_SYMBOL];
1093
+ const foreignRunId = value[STREAM_SERVER_RUN_ID_SYMBOL];
776
1094
  if (!name) {
777
1095
  const streamId = (global[STABLE_ULID] || defaultUlid)();
778
1096
  name = `strm_${streamId}`;
@@ -780,119 +1098,289 @@ function getStepReducers(global = globalThis, ops, runId, cryptoKey) {
780
1098
  .pipeThrough(getDeserializeStream(getStepRevivers(global, ops, runId, cryptoKey), cryptoKey))
781
1099
  .pipeTo(value));
782
1100
  }
783
- return { name };
1101
+ const s = { name };
1102
+ if (typeof foreignRunId === 'string')
1103
+ s.runId = foreignRunId;
1104
+ const foreignDeploymentId = value[STREAM_SERVER_DEPLOYMENT_ID_SYMBOL];
1105
+ if (typeof foreignDeploymentId === 'string') {
1106
+ s.deploymentId = foreignDeploymentId;
1107
+ }
1108
+ return s;
1109
+ },
1110
+ AbortController: (value) => {
1111
+ if (!global.AbortController ||
1112
+ typeof global.AbortController !== 'function' ||
1113
+ !(value instanceof global.AbortController))
1114
+ return false;
1115
+ return reduceAbortWithListener(value.signal, value, global, ops, runId, cryptoKey);
1116
+ },
1117
+ AbortSignal: (value) => {
1118
+ if (!global.AbortSignal ||
1119
+ typeof global.AbortSignal !== 'function' ||
1120
+ !(value instanceof global.AbortSignal))
1121
+ return false;
1122
+ return reduceAbortWithListener(value, value, global, ops, runId, cryptoKey);
784
1123
  },
785
1124
  };
786
1125
  }
787
- export function getCommonRevivers(global = globalThis) {
788
- function reviveArrayBuffer(value) {
789
- // Handle sentinel value for zero-length buffers
790
- const base64 = value === '.' ? '' : value;
791
- const buffer = Buffer.from(base64, 'base64');
792
- const arrayBuffer = new global.ArrayBuffer(buffer.length);
793
- const uint8Array = new global.Uint8Array(arrayBuffer);
794
- uint8Array.set(buffer);
795
- return arrayBuffer;
1126
+ /**
1127
+ * Cancel dangling abort-stream readers on any AbortController instances found
1128
+ * in the hydrated step arguments. Called after the step function returns
1129
+ * (success or failure) to prevent reader promises from keeping the serverless
1130
+ * function alive indefinitely.
1131
+ */
1132
+ export function cancelAbortReaders(...values) {
1133
+ const visited = new WeakSet();
1134
+ function cancelIfPresent(val) {
1135
+ const cancel = val[ABORT_READER_CANCEL];
1136
+ if (cancel && !cancel.signal.aborted) {
1137
+ cancel.abort();
1138
+ }
796
1139
  }
797
- return {
798
- ArrayBuffer: reviveArrayBuffer,
799
- BigInt: (value) => global.BigInt(value),
800
- BigInt64Array: (value) => {
801
- const ab = reviveArrayBuffer(value);
802
- return new global.BigInt64Array(ab);
803
- },
804
- BigUint64Array: (value) => {
805
- const ab = reviveArrayBuffer(value);
806
- return new global.BigUint64Array(ab);
807
- },
808
- Date: (value) => new global.Date(value),
809
- DOMException: (value) => {
810
- const error = new global.DOMException(value.message, value.name);
811
- if (value.stack !== undefined)
812
- error.stack = value.stack;
813
- // DOMException's constructor doesn't accept a cause option, so
814
- // we set it manually when present in the serialized data.
815
- if ('cause' in value)
816
- error.cause = value.cause;
817
- return error;
818
- },
819
- Error: (value) => {
820
- const error = new global.Error(value.message);
821
- error.name = value.name;
822
- error.stack = value.stack;
823
- return error;
824
- },
825
- Float32Array: (value) => {
826
- const ab = reviveArrayBuffer(value);
827
- return new global.Float32Array(ab);
828
- },
829
- Float64Array: (value) => {
830
- const ab = reviveArrayBuffer(value);
831
- return new global.Float64Array(ab);
832
- },
833
- Headers: (value) => new global.Headers(value),
834
- Int8Array: (value) => {
835
- const ab = reviveArrayBuffer(value);
836
- return new global.Int8Array(ab);
837
- },
838
- Int16Array: (value) => {
839
- const ab = reviveArrayBuffer(value);
840
- return new global.Int16Array(ab);
841
- },
842
- Int32Array: (value) => {
843
- const ab = reviveArrayBuffer(value);
844
- return new global.Int32Array(ab);
845
- },
846
- Map: (value) => new global.Map(value),
847
- RegExp: (value) => new global.RegExp(value.source, value.flags),
848
- Class: (value) => {
849
- const classId = value.classId;
850
- // Pass the global object to support VM contexts where classes are registered
851
- // on the VM's global rather than the host's globalThis
852
- const cls = getSerializationClass(classId, global);
853
- if (!cls) {
854
- throw new Error(`Class "${classId}" not found. Make sure the class is registered with registerSerializationClass.`);
855
- }
856
- return cls;
857
- },
858
- Instance: (value) => {
859
- const classId = value.classId;
860
- const data = value.data;
861
- // Look up the class by classId from the registry
862
- // Pass the global object to support VM contexts where classes are registered
863
- // on the VM's global rather than the host's globalThis
864
- const cls = getSerializationClass(classId, global);
865
- if (!cls) {
866
- throw new Error(`Class "${classId}" not found. Make sure the class is registered with registerSerializationClass.`);
1140
+ function walk(val) {
1141
+ if (val == null || typeof val !== 'object')
1142
+ return;
1143
+ if (visited.has(val))
1144
+ return;
1145
+ visited.add(val);
1146
+ if (val instanceof AbortController) {
1147
+ cancelIfPresent(val);
1148
+ cancelIfPresent(val.signal);
1149
+ return;
1150
+ }
1151
+ if (val instanceof AbortSignal) {
1152
+ cancelIfPresent(val);
1153
+ return;
1154
+ }
1155
+ if (Array.isArray(val)) {
1156
+ for (const item of val)
1157
+ walk(item);
1158
+ return;
1159
+ }
1160
+ if (val instanceof Map) {
1161
+ for (const v of val.values())
1162
+ walk(v);
1163
+ return;
1164
+ }
1165
+ if (val instanceof Set) {
1166
+ for (const v of val)
1167
+ walk(v);
1168
+ return;
1169
+ }
1170
+ // Request/Response expose `signal`/`body` as prototype getters, so
1171
+ // Object.values() won't find them. Descend explicitly.
1172
+ if (typeof Request !== 'undefined' && val instanceof Request) {
1173
+ walk(val.signal);
1174
+ return;
1175
+ }
1176
+ for (const v of Object.values(val))
1177
+ walk(v);
1178
+ }
1179
+ for (const v of values)
1180
+ walk(v);
1181
+ }
1182
+ /**
1183
+ * Sets up a stream reader on the controller that listens for an abort packet.
1184
+ * Returns the readerCancel controller so it can be stored on both the
1185
+ * controller and signal for cleanup by cancelAbortReaders.
1186
+ */
1187
+ function setupAbortStreamReader(controller, runId, streamName, ops) {
1188
+ const readerCancel = new AbortController();
1189
+ ops.push((async () => {
1190
+ try {
1191
+ const readable = new WorkflowServerReadableStream(runId, streamName);
1192
+ const reader = readable.getReader();
1193
+ const result = await Promise.race([
1194
+ reader.read(),
1195
+ new Promise((resolve) => {
1196
+ if (readerCancel.signal.aborted) {
1197
+ resolve({ value: undefined, done: true });
1198
+ return;
1199
+ }
1200
+ readerCancel.signal.addEventListener('abort', () => resolve({ value: undefined, done: true }), { once: true });
1201
+ }),
1202
+ ]);
1203
+ reader.releaseLock();
1204
+ if (result.value && !result.done) {
1205
+ try {
1206
+ // Hydrate via the same machinery the writer used so the reason
1207
+ // round-trips with full type fidelity. Encryption key (if any)
1208
+ // comes from the step context — set up by the step handler before
1209
+ // this reader runs. Fallback to undefined for external-context
1210
+ // revives (the hydrate path is encryption-key-tolerant).
1211
+ const ctxForKey = contextStorage.getStore();
1212
+ const data = (await hydrateStepArguments(result.value, runId, ctxForKey?.encryptionKey));
1213
+ controller.abort(data?.reason);
1214
+ }
1215
+ catch {
1216
+ controller.abort();
1217
+ }
867
1218
  }
868
- // Get the deserializer from the class
869
- const deserialize = cls[WORKFLOW_DESERIALIZE];
870
- if (typeof deserialize !== 'function') {
871
- throw new Error(`Class "${classId}" does not have a static ${String(WORKFLOW_DESERIALIZE)} method.`);
1219
+ }
1220
+ catch {
1221
+ // Stream read failed — signal won't propagate in real-time,
1222
+ // but hook-based propagation on next replay provides fallback
1223
+ }
1224
+ })());
1225
+ return readerCancel;
1226
+ }
1227
+ /**
1228
+ * Stores abort serialization symbols and the readerCancel controller
1229
+ * on both the controller and its signal.
1230
+ */
1231
+ function tagAbortPair(controller, value, readerCancel) {
1232
+ const taggedController = controller;
1233
+ const taggedSignal = controller.signal;
1234
+ taggedController[ABORT_STREAM_NAME] = value.streamName;
1235
+ taggedController[ABORT_HOOK_TOKEN] = value.hookToken;
1236
+ taggedSignal[ABORT_STREAM_NAME] = value.streamName;
1237
+ taggedSignal[ABORT_HOOK_TOKEN] = value.hookToken;
1238
+ if (readerCancel) {
1239
+ taggedController[ABORT_READER_CANCEL] = readerCancel;
1240
+ taggedSignal[ABORT_READER_CANCEL] = readerCancel;
1241
+ }
1242
+ }
1243
+ /**
1244
+ * Propagate abort-internal symbols from one signal to another. Used by the
1245
+ * Request reviver because `new Request(url, { signal })` copies the signal
1246
+ * internally — the constructed `request.signal` is a fresh AbortSignal that
1247
+ * doesn't carry symbols from the source.
1248
+ */
1249
+ function copyAbortInternals(src, dest) {
1250
+ const s = src;
1251
+ const d = dest;
1252
+ if (s[ABORT_STREAM_NAME] !== undefined) {
1253
+ d[ABORT_STREAM_NAME] = s[ABORT_STREAM_NAME];
1254
+ }
1255
+ if (s[ABORT_HOOK_TOKEN] !== undefined) {
1256
+ d[ABORT_HOOK_TOKEN] = s[ABORT_HOOK_TOKEN];
1257
+ }
1258
+ if (s[ABORT_READER_CANCEL] !== undefined) {
1259
+ d[ABORT_READER_CANCEL] = s[ABORT_READER_CANCEL];
1260
+ }
1261
+ }
1262
+ /**
1263
+ * Creates an AbortController with stream-backed abort propagation.
1264
+ * Used by step and external revivers where real abort signal behavior is needed.
1265
+ *
1266
+ * @param value - The serialized abort controller/signal data
1267
+ * @param ops - The ops array for tracking async work
1268
+ * @param runId - The workflow run ID (for stream reads)
1269
+ * @returns A real AbortController with patched abort() method
1270
+ */
1271
+ function reviveAbortController(value, ops, runId) {
1272
+ const controller = new AbortController();
1273
+ if (value.aborted) {
1274
+ tagAbortPair(controller, value);
1275
+ controller.abort(value.reason);
1276
+ }
1277
+ else if (value.streamName) {
1278
+ const readerCancel = setupAbortStreamReader(controller, runId, value.streamName, ops);
1279
+ tagAbortPair(controller, value, readerCancel);
1280
+ }
1281
+ else {
1282
+ tagAbortPair(controller, value);
1283
+ }
1284
+ // Override abort() to also write stream + resume hook (for step-initiated abort)
1285
+ const originalAbort = controller.abort.bind(controller);
1286
+ controller.abort = (reason) => {
1287
+ if (controller.signal.aborted)
1288
+ return;
1289
+ originalAbort(reason);
1290
+ const ctx = contextStorage.getStore();
1291
+ if (ctx) {
1292
+ ctx.ops.push((async () => {
1293
+ try {
1294
+ // Dehydrate the abort payload through the same machinery the hook
1295
+ // event uses so the `reason` round-trips with full type fidelity
1296
+ // (DOMException, custom errors, etc.) and respects the run's
1297
+ // encryption key — symmetric with what the suspension handler
1298
+ // writes for workflow-initiated aborts.
1299
+ const payload = await dehydrateStepArguments({ aborted: true, reason }, ctx.workflowMetadata.workflowRunId, ctx.encryptionKey);
1300
+ const writable = new WorkflowServerWritableStream(ctx.workflowMetadata.workflowRunId, value.streamName);
1301
+ const writer = writable.getWriter();
1302
+ await writer.write(payload);
1303
+ await writer.close();
1304
+ }
1305
+ catch {
1306
+ // Best-effort stream write
1307
+ }
1308
+ })());
1309
+ if (value.hookToken) {
1310
+ // The durable hook resume (which writes the `hook_received` event that
1311
+ // records this abort in the workflow's event log) must be committed
1312
+ // before the step completes. Otherwise the workflow continuation
1313
+ // enqueued by `step_completed` can advance past the abort — dispatching
1314
+ // a later step with a stale, non-aborted `signal` — before the event
1315
+ // exists. Route it to `preCompletionOps` (awaited inline before
1316
+ // completion) rather than `ops` (best-effort, background). The stream
1317
+ // write above stays in `ops`: it must fire ASAP to reach an in-flight
1318
+ // sibling step and is not the durable record.
1319
+ // Swallow errors here so the promise can only ever enforce ordering
1320
+ // when awaited (see the no-reject contract on
1321
+ // StepContext.preCompletionOps); a failed resume retries on next replay.
1322
+ const hookResume = (async () => {
1323
+ try {
1324
+ const { resumeHook: resumeHookFn } = await import('./runtime/resume-hook.js');
1325
+ await resumeHookFn(value.hookToken, {
1326
+ aborted: true,
1327
+ reason,
1328
+ });
1329
+ }
1330
+ catch {
1331
+ // Best-effort hook resume — retry on next replay
1332
+ }
1333
+ })();
1334
+ ctx.preCompletionOps.push(hookResume);
872
1335
  }
873
- // Deserialize the instance using the custom deserializer
874
- return deserialize.call(cls, data);
875
- },
876
- Set: (value) => new global.Set(value),
877
- URL: (value) => new global.URL(value),
878
- URLSearchParams: (value) => new global.URLSearchParams(value === '.' ? '' : value),
879
- Uint8Array: (value) => {
880
- const ab = reviveArrayBuffer(value);
881
- return new global.Uint8Array(ab);
882
- },
883
- Uint8ClampedArray: (value) => {
884
- const ab = reviveArrayBuffer(value);
885
- return new global.Uint8ClampedArray(ab);
886
- },
887
- Uint16Array: (value) => {
888
- const ab = reviveArrayBuffer(value);
889
- return new global.Uint16Array(ab);
890
- },
891
- Uint32Array: (value) => {
892
- const ab = reviveArrayBuffer(value);
893
- return new global.Uint32Array(ab);
894
- },
1336
+ }
895
1337
  };
1338
+ return controller;
1339
+ }
1340
+ /**
1341
+ * Revives just an AbortSignal without the patched abort() overhead.
1342
+ * Used when only a signal (not a controller) was serialized.
1343
+ */
1344
+ function reviveAbortSignal(value, ops, runId) {
1345
+ const controller = new AbortController();
1346
+ if (value.aborted) {
1347
+ tagAbortPair(controller, value);
1348
+ controller.abort(value.reason);
1349
+ }
1350
+ else if (value.streamName) {
1351
+ const readerCancel = setupAbortStreamReader(controller, runId, value.streamName, ops);
1352
+ tagAbortPair(controller, value, readerCancel);
1353
+ }
1354
+ else {
1355
+ tagAbortPair(controller, value);
1356
+ }
1357
+ return controller.signal;
1358
+ }
1359
+ /**
1360
+ * Base revivers shared across all serialization boundaries.
1361
+ * Composes: class + common revivers from the modular modules.
1362
+ *
1363
+ * This is exported because serialization-format.ts and other files reference it.
1364
+ */
1365
+ export function getCommonRevivers(global = globalThis) {
1366
+ return {
1367
+ ...getClassRevivers(global),
1368
+ ...getCommonReviversFromModule(global),
1369
+ };
1370
+ }
1371
+ /**
1372
+ * Resolve the encrypt-only key needed when a child writes into another run's
1373
+ * stream. New descriptors include the owner's deployment ID; descriptors
1374
+ * created by older SDK versions fall back to loading the owning run.
1375
+ */
1376
+ async function getForwardedWritableEncryptionKey(runId, deploymentId) {
1377
+ const world = await getWorldLazy();
1378
+ if (!world.getEncryptionKeyForRun)
1379
+ return undefined;
1380
+ const rawKey = deploymentId
1381
+ ? await world.getEncryptionKeyForRun(runId, { deploymentId })
1382
+ : await world.getEncryptionKeyForRun(await world.runs.get(runId));
1383
+ return rawKey ? await importKey(rawKey, ['encrypt']) : undefined;
896
1384
  }
897
1385
  /**
898
1386
  * Revivers for deserialization boundary from the client side,
@@ -907,18 +1395,31 @@ export function getExternalRevivers(global = globalThis, ops, runId, cryptoKey)
907
1395
  ...getCommonRevivers(global),
908
1396
  // StepFunction should not be returned from workflows to clients
909
1397
  StepFunction: () => {
910
- throw new Error('Step functions cannot be deserialized in client context. Step functions should not be returned from workflows.');
1398
+ throw new SerializationError('Step functions cannot be deserialized in client context. Step functions should not be returned from workflows.', {
1399
+ hint: 'A step function reference reached the client. Return a serializable value (e.g. the step result) instead of the step itself.',
1400
+ });
911
1401
  },
912
1402
  WorkflowFunction: (value) => Object.assign(() => {
913
- throw new Error('Workflow functions cannot be called directly. Use start() to invoke them.');
1403
+ throw new SerializationError('Workflow functions cannot be called directly. Use start() to invoke them.', {
1404
+ hint: 'Wrap the workflow with `start(workflowFn, { ... })` from `workflow` to begin a run instead of invoking it like a normal function.',
1405
+ });
914
1406
  }, { workflowId: value.workflowId }),
915
1407
  Request: (value) => {
916
- return new global.Request(value.url, {
1408
+ const init = {
917
1409
  method: value.method,
918
1410
  headers: new global.Headers(value.headers),
919
1411
  body: value.body,
920
1412
  duplex: value.duplex,
921
- });
1413
+ };
1414
+ if (value.signal)
1415
+ init.signal = value.signal;
1416
+ const request = new global.Request(value.url, init);
1417
+ // The Request constructor creates an internal signal copy, so the
1418
+ // abort-internal symbols set by reviveAbortSignal don't propagate.
1419
+ // Re-tag the request's own signal so cancelAbortReaders can find it.
1420
+ if (value.signal)
1421
+ copyAbortInternals(value.signal, request.signal);
1422
+ return request;
922
1423
  },
923
1424
  Response: (value) => {
924
1425
  // Note: Response constructor only accepts status, statusText, and headers
@@ -938,13 +1439,24 @@ export function getExternalRevivers(global = globalThis, ops, runId, cryptoKey)
938
1439
  const response = new global.Response(bodyInit);
939
1440
  return response.body;
940
1441
  }
941
- const readable = new WorkflowServerReadableStream(runId, value.name, value.startIndex);
942
1442
  if (value.type === 'bytes') {
943
- // For byte streams, use flushable pipe with lock polling
1443
+ // For byte streams, use flushable pipe with lock polling.
1444
+ // If the producer wrote framed bytes (framing === 'framed-v1'),
1445
+ // unwrap the length-prefix envelope before handing chunks to
1446
+ // the user. Absent / 'raw' framing means legacy raw bytes —
1447
+ // pipe through unchanged for backwards compatibility.
1448
+ //
1449
+ // No auto-reconnect here yet: raw byte streams have no wire
1450
+ // framing to count consumed chunks with. Framed-v1 byte streams
1451
+ // make frame counting possible, so extending the reconnecting
1452
+ // reader to them is a separate follow-up.
1453
+ const readable = new WorkflowServerReadableStream(runId, value.name, value.startIndex);
944
1454
  const state = createFlushableState();
945
1455
  ops.push(state.promise);
946
- // Create an identity transform to give the user a readable
947
- const { readable: userReadable, writable } = new global.TransformStream();
1456
+ // Create an identity (or unframing) transform to give the user a readable
1457
+ const { readable: userReadable, writable } = value.framing === 'framed-v1'
1458
+ ? getByteUnframingStream()
1459
+ : new global.TransformStream();
948
1460
  // Start the flushable pipe in the background
949
1461
  flushablePipe(readable, writable, state).catch(() => {
950
1462
  // Errors are handled via state.reject
@@ -954,6 +1466,10 @@ export function getExternalRevivers(global = globalThis, ops, runId, cryptoKey)
954
1466
  return userReadable;
955
1467
  }
956
1468
  else {
1469
+ // Non-byte streams carry length-prefixed frames, so we can count
1470
+ // completed frames and transparently reconnect when the server
1471
+ // stream connection times out mid-run.
1472
+ const readable = createReconnectingFramedStream(runId, value.name, value.startIndex);
957
1473
  const transform = getDeserializeStream(getExternalRevivers(global, ops, runId, cryptoKey), cryptoKey);
958
1474
  const state = createFlushableState();
959
1475
  ops.push(state.promise);
@@ -967,8 +1483,15 @@ export function getExternalRevivers(global = globalThis, ops, runId, cryptoKey)
967
1483
  }
968
1484
  },
969
1485
  WritableStream: (value) => {
970
- const serialize = getSerializeStream(getExternalReducers(global, ops, runId, cryptoKey), cryptoKey);
971
- const serverWritable = new WorkflowServerWritableStream(runId, value.name);
1486
+ // Same handling as `getStepRevivers.WritableStream` see comments
1487
+ // there for the cross-run case (writable carries `runId` from
1488
+ // parent → child forwarding via `start()`).
1489
+ const targetRunId = typeof value.runId === 'string' ? value.runId : runId;
1490
+ const targetKey = targetRunId === runId
1491
+ ? cryptoKey
1492
+ : getForwardedWritableEncryptionKey(targetRunId, value.deploymentId);
1493
+ const serialize = getSerializeStream(getExternalReducers(global, ops, targetRunId, targetKey), targetKey);
1494
+ const serverWritable = new WorkflowServerWritableStream(targetRunId, value.name);
972
1495
  // Create flushable state for this stream
973
1496
  const state = createFlushableState();
974
1497
  ops.push(state.promise);
@@ -978,8 +1501,24 @@ export function getExternalRevivers(global = globalThis, ops, runId, cryptoKey)
978
1501
  });
979
1502
  // Start polling to detect when user releases lock
980
1503
  pollWritableLock(serialize.writable, state);
1504
+ Object.defineProperty(serialize.writable, STREAM_NAME_SYMBOL, {
1505
+ value: value.name,
1506
+ writable: false,
1507
+ });
1508
+ Object.defineProperty(serialize.writable, STREAM_SERVER_RUN_ID_SYMBOL, {
1509
+ value: targetRunId,
1510
+ writable: false,
1511
+ });
1512
+ if (typeof value.deploymentId === 'string') {
1513
+ Object.defineProperty(serialize.writable, STREAM_SERVER_DEPLOYMENT_ID_SYMBOL, {
1514
+ value: value.deploymentId,
1515
+ writable: false,
1516
+ });
1517
+ }
981
1518
  return serialize.writable;
982
1519
  },
1520
+ AbortController: (value) => reviveAbortController(value, ops, runId),
1521
+ AbortSignal: (value) => reviveAbortSignal(value, ops, runId),
983
1522
  };
984
1523
  }
985
1524
  /**
@@ -991,27 +1530,11 @@ export function getExternalRevivers(global = globalThis, ops, runId, cryptoKey)
991
1530
  * @returns
992
1531
  */
993
1532
  export function getWorkflowRevivers(global = globalThis) {
994
- // Get the useStep function from the VM's globalThis
995
- // This is set up by the workflow runner in workflow.ts
996
- // Use Symbol.for directly to access the symbol on the global object
997
- const useStep = global[Symbol.for('WORKFLOW_USE_STEP')];
998
1533
  return {
999
1534
  ...getCommonRevivers(global),
1000
- // StepFunction reviver for workflow context - returns useStep wrapper
1001
- // This allows step functions passed as arguments to start() to be called directly
1002
- // from workflow code, just like step functions defined in the same file
1003
- StepFunction: (value) => {
1004
- const stepId = value.stepId;
1005
- const closureVars = value.closureVars;
1006
- if (!useStep) {
1007
- throw new Error('WORKFLOW_USE_STEP not found on global object. Step functions cannot be deserialized outside workflow context.');
1008
- }
1009
- if (closureVars) {
1010
- // For step functions with closure variables, create a wrapper that provides them
1011
- return useStep(stepId, () => closureVars);
1012
- }
1013
- return useStep(stepId);
1014
- },
1535
+ // StepFunction reviver for workflow context - uses the modular reviver
1536
+ // which calls WORKFLOW_USE_STEP from global to reconstruct step proxies
1537
+ ...getStepFunctionReviver(global),
1015
1538
  Request: (value) => {
1016
1539
  Object.setPrototypeOf(value, global.Request.prototype);
1017
1540
  const responseWritable = value.responseWritable;
@@ -1019,7 +1542,9 @@ export function getWorkflowRevivers(global = globalThis) {
1019
1542
  value[WEBHOOK_RESPONSE_WRITABLE] = responseWritable;
1020
1543
  delete value.responseWritable;
1021
1544
  value.respondWith = () => {
1022
- throw new Error('`respondWith()` must be called from within a step function');
1545
+ throw new SerializationError('`respondWith()` must be called from within a step function.', {
1546
+ hint: 'Move the `respondWith(...)` call inside a `"use step"` function — it cannot be invoked from a workflow context.',
1547
+ });
1023
1548
  };
1024
1549
  }
1025
1550
  return value;
@@ -1027,7 +1552,9 @@ export function getWorkflowRevivers(global = globalThis) {
1027
1552
  // Workflow function reviver for workflow context — returns a function-like
1028
1553
  // object with .workflowId that mimics what the SWC compiler produces,
1029
1554
  WorkflowFunction: (value) => Object.assign(() => {
1030
- throw new Error('Workflow functions cannot be called directly. Use start() to invoke them.');
1555
+ throw new SerializationError('Workflow functions cannot be called directly. Use start() to invoke them.', {
1556
+ hint: 'Wrap the workflow with `start(workflowFn, { ... })` from `workflow` to begin a run instead of invoking it like a normal function.',
1557
+ });
1031
1558
  }, { workflowId: value.workflowId }),
1032
1559
  Response: (value) => {
1033
1560
  Object.setPrototypeOf(value, global.Response.prototype);
@@ -1054,15 +1581,64 @@ export function getWorkflowRevivers(global = globalThis) {
1054
1581
  value: value.type,
1055
1582
  writable: false,
1056
1583
  },
1584
+ // Carry the wire-framing decision through the workflow VM so
1585
+ // that when the handle is later passed to a step (which reads
1586
+ // the actual bytes from the server) we know whether to unframe.
1587
+ // Defaults to undefined for streams whose serialized ref didn't
1588
+ // carry the field — those are treated as legacy raw bytes.
1589
+ [STREAM_FRAMING_SYMBOL]: {
1590
+ value: value.framing,
1591
+ writable: false,
1592
+ },
1057
1593
  });
1058
1594
  },
1059
1595
  WritableStream: (value) => {
1060
- return Object.create(global.WritableStream.prototype, {
1596
+ const descriptor = {
1061
1597
  [STREAM_NAME_SYMBOL]: {
1062
1598
  value: value.name,
1063
1599
  writable: false,
1064
1600
  },
1065
- });
1601
+ };
1602
+ // Preserve the foreign runId, if present, so that when the
1603
+ // handle is later passed to a step the workflow reducer can
1604
+ // forward it through to the step reviver.
1605
+ if (typeof value.runId === 'string') {
1606
+ descriptor[STREAM_SERVER_RUN_ID_SYMBOL] = {
1607
+ value: value.runId,
1608
+ writable: false,
1609
+ };
1610
+ }
1611
+ if (typeof value.deploymentId === 'string') {
1612
+ descriptor[STREAM_SERVER_DEPLOYMENT_ID_SYMBOL] = {
1613
+ value: value.deploymentId,
1614
+ writable: false,
1615
+ };
1616
+ }
1617
+ return Object.create(global.WritableStream.prototype, descriptor);
1618
+ },
1619
+ // AbortController/AbortSignal revived inside the workflow VM. Use the
1620
+ // real WorkflowAbortSignal class so addEventListener('abort', fn) actually
1621
+ // fires when the signal aborts (the previous no-op stub silently dropped
1622
+ // listener registrations — silent correctness bug for natural patterns
1623
+ // like `signal.addEventListener('abort', fn)` after receiving a deserialized
1624
+ // signal). The signal does not own a hook subscription here — abort state
1625
+ // is delivered via the existing replay machinery on the source side.
1626
+ AbortController: (value) => {
1627
+ const signal = new WorkflowAbortSignal(value.streamName, value.hookToken);
1628
+ if (value.aborted)
1629
+ signal._setAborted(value.reason);
1630
+ return {
1631
+ [ABORT_STREAM_NAME]: value.streamName,
1632
+ [ABORT_HOOK_TOKEN]: value.hookToken,
1633
+ signal,
1634
+ abort: () => { },
1635
+ };
1636
+ },
1637
+ AbortSignal: (value) => {
1638
+ const signal = new WorkflowAbortSignal(value.streamName, value.hookToken);
1639
+ if (value.aborted)
1640
+ signal._setAborted(value.reason);
1641
+ return signal;
1066
1642
  },
1067
1643
  };
1068
1644
  }
@@ -1075,63 +1651,95 @@ export function getWorkflowRevivers(global = globalThis) {
1075
1651
  * @param runId
1076
1652
  * @returns
1077
1653
  */
1078
- function getStepRevivers(global = globalThis, ops, runId, cryptoKey) {
1654
+ function getStepRevivers(global = globalThis, ops, runId, cryptoKey, deploymentId) {
1079
1655
  return {
1080
1656
  ...getCommonRevivers(global),
1081
1657
  // StepFunction reviver for step context - returns raw step function
1082
- // with closure variable support via AsyncLocalStorage
1658
+ // with closure variable support via AsyncLocalStorage.
1659
+ //
1660
+ // Handles four independent flags from the serialized payload:
1661
+ // - `closureVars`: invoke the body inside an AsyncLocalStorage frame
1662
+ // so the SWC-emitted `WORKFLOW_STEP_CONTEXT_STORAGE` IIFE in the
1663
+ // hoisted body can pull the closure variables back out.
1664
+ // - `boundThis`: a `this` value captured by
1665
+ // `useStep(...).bind(this)` in the workflow bundle (lexical-`this`
1666
+ // arrow steps). The wrapper invokes the body via
1667
+ // `stepFn.apply(boundThis, args)` so the body sees the same
1668
+ // `this` it would have had in the workflow bundle. Property
1669
+ // presence — not truthiness — is significant because
1670
+ // `bind(null)` and `bind(undefined)` are both legal and should
1671
+ // round-trip faithfully.
1672
+ // - `boundArgs`: prefilled args from
1673
+ // `useStep(...).bind(thisArg, x, y)`. Prepended to the call args
1674
+ // so partial application survives serialization.
1083
1675
  StepFunction: (value) => {
1084
1676
  const stepId = value.stepId;
1085
1677
  const closureVars = value.closureVars;
1678
+ const hasBoundThis = 'boundThis' in value;
1679
+ const boundThis = hasBoundThis ? value.boundThis : undefined;
1680
+ const boundArgs = Array.isArray(value.boundArgs) ? value.boundArgs : [];
1086
1681
  const stepFn = getStepFunction(stepId);
1087
1682
  if (!stepFn) {
1088
- throw new Error(`Step function "${stepId}" not found. Make sure the step function is registered.`);
1683
+ throw new SerializationError(`Step function "${stepId}" not found. Make sure the step function is registered.`, {
1684
+ hint: 'Make sure the step file is included in your build (i.e. it is listed in the workflow manifest), and that the SWC plugin is configured for the file.',
1685
+ });
1686
+ }
1687
+ // Fast path: nothing to wrap.
1688
+ if (!closureVars && !hasBoundThis && boundArgs.length === 0) {
1689
+ return stepFn;
1089
1690
  }
1090
- // If closure variables were serialized, return a wrapper function
1091
- // that sets up AsyncLocalStorage context when invoked
1092
- if (closureVars) {
1093
- const wrappedStepFn = ((...args) => {
1094
- // Get the current context from AsyncLocalStorage
1691
+ const wrappedStepFn = function (...args) {
1692
+ const callThis = hasBoundThis ? boundThis : this;
1693
+ const callArgs = boundArgs.length > 0 ? [...boundArgs, ...args] : args;
1694
+ if (closureVars) {
1095
1695
  const currentContext = contextStorage.getStore();
1096
1696
  if (!currentContext) {
1097
- throw new Error('Cannot call step function with closure variables outside step context');
1697
+ throw new WorkflowRuntimeError('Cannot call step function with closure variables outside step context');
1098
1698
  }
1099
- // Create a new context with the closure variables merged in
1100
1699
  const newContext = {
1101
1700
  ...currentContext,
1102
1701
  closureVars,
1103
1702
  };
1104
- // Run the step function with the new context that includes closure vars
1105
- return contextStorage.run(newContext, () => stepFn(...args));
1106
- });
1107
- // Copy properties from original step function
1108
- Object.defineProperty(wrappedStepFn, 'name', {
1109
- value: stepFn.name,
1110
- });
1111
- Object.defineProperty(wrappedStepFn, 'stepId', {
1112
- value: stepId,
1113
- writable: false,
1114
- enumerable: false,
1115
- configurable: false,
1116
- });
1117
- if (stepFn.maxRetries !== undefined) {
1118
- wrappedStepFn.maxRetries = stepFn.maxRetries;
1703
+ return contextStorage.run(newContext, () => stepFn.apply(callThis, callArgs));
1119
1704
  }
1120
- return wrappedStepFn;
1705
+ return stepFn.apply(callThis, callArgs);
1706
+ };
1707
+ // Copy properties from original step function
1708
+ Object.defineProperty(wrappedStepFn, 'name', {
1709
+ value: stepFn.name,
1710
+ });
1711
+ Object.defineProperty(wrappedStepFn, 'stepId', {
1712
+ value: stepId,
1713
+ writable: false,
1714
+ enumerable: false,
1715
+ configurable: false,
1716
+ });
1717
+ if (stepFn.maxRetries !== undefined) {
1718
+ wrappedStepFn.maxRetries = stepFn.maxRetries;
1121
1719
  }
1122
- return stepFn;
1720
+ return wrappedStepFn;
1123
1721
  },
1124
1722
  WorkflowFunction: (value) => Object.assign(() => {
1125
- throw new Error('Workflow functions cannot be called directly. Use start() to invoke them.');
1723
+ throw new SerializationError('Workflow functions cannot be called directly. Use start() to invoke them.', {
1724
+ hint: 'Wrap the workflow with `start(workflowFn, { ... })` from `workflow` to begin a run instead of invoking it like a normal function.',
1725
+ });
1126
1726
  }, { workflowId: value.workflowId }),
1127
1727
  Request: (value) => {
1128
1728
  const responseWritable = value.responseWritable;
1129
- const request = new global.Request(value.url, {
1729
+ const init = {
1130
1730
  method: value.method,
1131
1731
  headers: new global.Headers(value.headers),
1132
1732
  body: value.body,
1133
1733
  duplex: value.duplex,
1134
- });
1734
+ };
1735
+ if (value.signal)
1736
+ init.signal = value.signal;
1737
+ const request = new global.Request(value.url, init);
1738
+ // The Request constructor creates an internal signal copy, so the
1739
+ // abort-internal symbols set by reviveAbortSignal don't propagate.
1740
+ // Re-tag the request's own signal so cancelAbortReaders can find it.
1741
+ if (value.signal)
1742
+ copyAbortInternals(value.signal, request.signal);
1135
1743
  if (responseWritable) {
1136
1744
  request.respondWith = async (response) => {
1137
1745
  const writer = responseWritable.getWriter();
@@ -1161,11 +1769,17 @@ function getStepRevivers(global = globalThis, ops, runId, cryptoKey) {
1161
1769
  }
1162
1770
  const readable = new WorkflowServerReadableStream(runId, value.name);
1163
1771
  if (value.type === 'bytes') {
1164
- // For byte streams, use flushable pipe with lock polling
1772
+ // For byte streams, use flushable pipe with lock polling.
1773
+ // If the producer wrote framed bytes (framing === 'framed-v1'),
1774
+ // unwrap the length-prefix envelope before handing chunks to
1775
+ // the user step. Absent / 'raw' framing means legacy raw bytes —
1776
+ // pipe through unchanged for backwards compatibility.
1165
1777
  const state = createFlushableState();
1166
1778
  ops.push(state.promise);
1167
- // Create an identity transform to give the user a readable
1168
- const { readable: userReadable, writable } = new global.TransformStream();
1779
+ // Create an identity (or unframing) transform to give the user a readable
1780
+ const { readable: userReadable, writable } = value.framing === 'framed-v1'
1781
+ ? getByteUnframingStream()
1782
+ : new global.TransformStream();
1169
1783
  // Start the flushable pipe in the background
1170
1784
  flushablePipe(readable, writable, state).catch(() => {
1171
1785
  // Errors are handled via state.reject
@@ -1175,7 +1789,7 @@ function getStepRevivers(global = globalThis, ops, runId, cryptoKey) {
1175
1789
  return userReadable;
1176
1790
  }
1177
1791
  else {
1178
- const transform = getDeserializeStream(getStepRevivers(global, ops, runId, cryptoKey), cryptoKey);
1792
+ const transform = getDeserializeStream(getStepRevivers(global, ops, runId, cryptoKey, deploymentId), cryptoKey);
1179
1793
  const state = createFlushableState();
1180
1794
  ops.push(state.promise);
1181
1795
  // Start the flushable pipe in the background
@@ -1188,8 +1802,29 @@ function getStepRevivers(global = globalThis, ops, runId, cryptoKey) {
1188
1802
  }
1189
1803
  },
1190
1804
  WritableStream: (value) => {
1191
- const serialize = getSerializeStream(getStepReducers(global, ops, runId, cryptoKey), cryptoKey);
1192
- const serverWritable = new WorkflowServerWritableStream(runId, value.name);
1805
+ // Same-run case: the writable belongs to the current run. Use the
1806
+ // local cryptoKey and write to the local runId's server stream.
1807
+ //
1808
+ // Cross-run case (parent → child via `start()`): the descriptor
1809
+ // carries the original `runId` and `name`. Open a server writable
1810
+ // against the original `(runId, name)` and resolve THAT run's key
1811
+ // for encryption. The resolution is async but doesn't need to
1812
+ // block reviver return — `getSerializeStream` accepts the
1813
+ // `Promise<CryptoKey | undefined>` directly and awaits it lazily
1814
+ // on the first chunk written. The key is imported encrypt-only
1815
+ // so the receiving run can never decrypt anything else on the
1816
+ // owning run's stream — it can only contribute new writes.
1817
+ const targetRunId = typeof value.runId === 'string' ? value.runId : runId;
1818
+ const targetDeploymentId = typeof value.deploymentId === 'string'
1819
+ ? value.deploymentId
1820
+ : targetRunId === runId
1821
+ ? deploymentId
1822
+ : undefined;
1823
+ const targetKey = targetRunId === runId
1824
+ ? cryptoKey
1825
+ : getForwardedWritableEncryptionKey(targetRunId, targetDeploymentId);
1826
+ const serialize = getSerializeStream(getStepReducers(global, ops, targetRunId, targetKey), targetKey);
1827
+ const serverWritable = new WorkflowServerWritableStream(targetRunId, value.name);
1193
1828
  // Create flushable state for this stream
1194
1829
  const state = createFlushableState();
1195
1830
  ops.push(state.promise);
@@ -1199,59 +1834,60 @@ function getStepRevivers(global = globalThis, ops, runId, cryptoKey) {
1199
1834
  });
1200
1835
  // Start polling to detect when user releases lock
1201
1836
  pollWritableLock(serialize.writable, state);
1837
+ // Record the underlying `(runId, name)` so downstream reducers can
1838
+ // recognize that this writable is already backed by a workflow
1839
+ // server stream. When forwarded across `start()` again — e.g.
1840
+ // the child passes this writable on to a grandchild — the
1841
+ // external reducer needs both to emit the original `runId` in
1842
+ // the descriptor.
1843
+ Object.defineProperty(serialize.writable, STREAM_NAME_SYMBOL, {
1844
+ value: value.name,
1845
+ writable: false,
1846
+ });
1847
+ Object.defineProperty(serialize.writable, STREAM_SERVER_RUN_ID_SYMBOL, {
1848
+ value: targetRunId,
1849
+ writable: false,
1850
+ });
1851
+ if (targetDeploymentId) {
1852
+ Object.defineProperty(serialize.writable, STREAM_SERVER_DEPLOYMENT_ID_SYMBOL, {
1853
+ value: targetDeploymentId,
1854
+ writable: false,
1855
+ });
1856
+ }
1202
1857
  return serialize.writable;
1203
1858
  },
1859
+ AbortController: (value) => reviveAbortController(value, ops, runId),
1860
+ AbortSignal: (value) => reviveAbortSignal(value, ops, runId),
1204
1861
  };
1205
1862
  }
1206
1863
  // ============================================================================
1207
1864
  // Encryption Helpers
1208
1865
  // ============================================================================
1866
+ // These delegate to the modular `encrypt`/`decrypt` from `./serialization/encryption.js`
1867
+ // but are kept as named exports for backwards compatibility with existing consumers.
1209
1868
  /**
1210
1869
  * Encrypt data if the world supports encryption.
1211
1870
  * Returns original data if encryption is not available.
1212
1871
  *
1213
- * @param data - Serialized data to encrypt
1214
- * @param key - Encryption key (undefined to skip encryption)
1215
- * @param context - Encryption context with runId
1216
- * @returns Encrypted data if encryption available, original data otherwise
1872
+ * @deprecated Use `encrypt` from `./serialization/encryption.js` instead.
1217
1873
  */
1218
1874
  export async function maybeEncrypt(data, key) {
1219
- if (!key)
1220
- return data;
1221
- const encrypted = await aesGcmEncrypt(key, data);
1222
- return encodeWithFormatPrefix(SerializationFormat.ENCRYPTED, encrypted);
1875
+ return (await encrypt(data, key));
1223
1876
  }
1224
1877
  /**
1225
1878
  * Decrypt data if it has the 'encr' prefix.
1226
1879
  *
1227
- * @param data - Data that may be encrypted
1228
- * @param key - Encryption key (undefined if no key available)
1229
- * @returns Decrypted data if encrypted, original data otherwise
1230
- * @throws {WorkflowRuntimeError} If the data is encrypted but no key is
1231
- * available. Callers (e.g., `Run.pollReturnValue()`, `hydrateStepReturnValue`)
1232
- * should be aware this can surface as a rejected promise during key rotation
1233
- * or misconfiguration scenarios.
1880
+ * @deprecated Use `decrypt` from `./serialization/encryption.js` instead.
1234
1881
  */
1235
1882
  export async function maybeDecrypt(data, key) {
1236
- // Legacy specVersion 1 runs stored event data as plain JSON arrays
1237
- // (not binary Uint8Array). Pass through as-is for backwards compat.
1238
- if (!(data instanceof Uint8Array)) {
1239
- return data;
1240
- }
1241
- if (isEncrypted(data)) {
1242
- if (!key) {
1243
- throw new WorkflowRuntimeError('Encrypted data encountered but no encryption key is available. ' +
1244
- 'Encryption is not configured or no key was provided for this run.');
1245
- }
1246
- // Strip the 'encr' format prefix — the prefix is a core framing concern
1247
- const { payload } = decodeFormatPrefix(data);
1248
- return aesGcmDecrypt(key, payload);
1249
- }
1250
- return data;
1883
+ return decrypt(data, key);
1251
1884
  }
1252
1885
  // ============================================================================
1253
1886
  // Dehydrate / Hydrate Functions
1254
1887
  // ============================================================================
1888
+ // These delegate to the modular mode modules (workflow, step, client) passing
1889
+ // mode-specific stream and Request/Response reducers/revivers as extra options.
1890
+ // The v1Compat path is handled inline before delegating to the modules.
1255
1891
  /**
1256
1892
  * Called from the `start()` function to serialize the workflow arguments
1257
1893
  * into a format that can be saved to the database and then hydrated from
@@ -1263,147 +1899,281 @@ export async function maybeDecrypt(data, key) {
1263
1899
  * @param ops - Promise array for stream operations
1264
1900
  * @param global - Global object for serialization context
1265
1901
  * @param v1Compat - Enable legacy v1 compatibility mode
1902
+ * @param framedByteStreams - Whether the target run can decode wire-framed
1903
+ * byte streams. Should match the target deployment's capability — see
1904
+ * `getRunCapabilities` in `capabilities.ts`. Defaults to `false` for
1905
+ * backwards compatibility with older runs.
1266
1906
  * @returns The dehydrated value as binary data (Uint8Array) with format prefix
1267
1907
  */
1268
- export async function dehydrateWorkflowArguments(value, runId, key, ops = [], global = globalThis, v1Compat = false) {
1908
+ export async function dehydrateWorkflowArguments(value, runId, key, ops = [], global = globalThis, v1Compat = false, framedByteStreams = false, compression = false) {
1909
+ if (v1Compat) {
1910
+ const str = stringify(value, getExternalReducers(global, ops, runId, key, framedByteStreams));
1911
+ return revive(str);
1912
+ }
1269
1913
  try {
1270
- const str = stringify(value, getExternalReducers(global, ops, runId, key));
1271
- if (v1Compat) {
1272
- return revive(str);
1273
- }
1274
- const payload = new TextEncoder().encode(str);
1275
- const serialized = encodeWithFormatPrefix(SerializationFormat.DEVALUE_V1, payload);
1276
- // Encrypt if world supports encryption
1277
- return maybeEncrypt(serialized, key);
1914
+ const compressionStats = {};
1915
+ const result = await clientModule.serialize(value, key, {
1916
+ global,
1917
+ extraReducers: getStreamAndRequestReducers(getExternalReducers(global, ops, runId, key, framedByteStreams)),
1918
+ compression,
1919
+ compressionStats,
1920
+ });
1921
+ await recordCompression(compressionStats, 'serialize');
1922
+ return result;
1278
1923
  }
1279
1924
  catch (error) {
1280
- throw new WorkflowRuntimeError(formatSerializationError('workflow arguments', error), { slug: 'serialization-failed', cause: error });
1925
+ const cause = unwrapSerializationCause(error);
1926
+ const { message, hint } = formatSerializationError('workflow arguments', cause);
1927
+ throw new SerializationError(message, { hint, cause });
1281
1928
  }
1282
1929
  }
1283
1930
  /**
1284
1931
  * Called from workflow execution environment to hydrate the workflow
1285
1932
  * arguments from the database at the start of workflow execution.
1286
- *
1287
- * @param value - Binary serialized data (Uint8Array) with format prefix
1288
- * @param _runId - Workflow run ID (reserved for future decryption context; decryption is currently driven solely by the provided key)
1289
- * @param key - Encryption key (undefined to skip decryption)
1290
- * @param global - Global object for deserialization context
1291
- * @param extraRevivers - Additional revivers for custom types
1292
- * @returns The hydrated value
1293
1933
  */
1294
1934
  export async function hydrateWorkflowArguments(value, _runId, key, global = globalThis, extraRevivers = {}) {
1295
- // Decrypt if needed
1296
- const decrypted = await maybeDecrypt(value, key);
1297
- // Legacy specVersion 1 runs stored data as plain JSON arrays (not binary).
1298
- // These pass through maybeDecrypt unchanged and are deserialized directly
1299
- // via devalue's unflatten().
1300
- if (!(decrypted instanceof Uint8Array)) {
1301
- return unflatten(decrypted, {
1302
- ...getWorkflowRevivers(global),
1935
+ const compressionStats = {};
1936
+ const inflated = await decompress(await maybeDecrypt(value, key), compressionStats);
1937
+ await recordCompression(compressionStats, 'deserialize');
1938
+ return workflowModule.deserialize(inflated, {
1939
+ global,
1940
+ extraRevivers: {
1941
+ ...getStreamAndRequestRevivers(getWorkflowRevivers(global)),
1303
1942
  ...extraRevivers,
1943
+ },
1944
+ });
1945
+ }
1946
+ /**
1947
+ * Dehydrate workflow return value for storage.
1948
+ */
1949
+ export async function dehydrateWorkflowReturnValue(value, _runId, key, global = globalThis, v1Compat = false, compression = false) {
1950
+ if (v1Compat) {
1951
+ const str = stringify(value, getWorkflowReducers(global));
1952
+ return revive(str);
1953
+ }
1954
+ try {
1955
+ const compressionStats = {};
1956
+ const result = await stepModule.serialize(value, key, {
1957
+ global,
1958
+ extraReducers: getStreamAndRequestReducers(getWorkflowReducers(global)),
1959
+ compression,
1960
+ compressionStats,
1304
1961
  });
1962
+ await recordCompression(compressionStats, 'serialize');
1963
+ return result;
1305
1964
  }
1306
- const { format, payload } = decodeFormatPrefix(decrypted);
1307
- if (format === SerializationFormat.DEVALUE_V1) {
1308
- const str = new TextDecoder().decode(payload);
1309
- const obj = parse(str, {
1310
- ...getWorkflowRevivers(global),
1965
+ catch (error) {
1966
+ const cause = unwrapSerializationCause(error);
1967
+ const { message, hint } = formatSerializationError('workflow return value', cause);
1968
+ throw new SerializationError(message, { hint, cause });
1969
+ }
1970
+ }
1971
+ /**
1972
+ * Called from the client side to hydrate the workflow return value
1973
+ * of a completed workflow run.
1974
+ */
1975
+ export async function hydrateWorkflowReturnValue(value, runId, key, ops = [], global = globalThis, extraRevivers = {}) {
1976
+ const compressionStats = {};
1977
+ const result = await clientModule.deserialize(value, key, {
1978
+ global,
1979
+ extraRevivers: {
1980
+ ...getStreamAndRequestRevivers(getExternalRevivers(global, ops, runId, key)),
1311
1981
  ...extraRevivers,
1982
+ },
1983
+ compressionStats,
1984
+ });
1985
+ await recordCompression(compressionStats, 'deserialize');
1986
+ return result;
1987
+ }
1988
+ /**
1989
+ * Called from the workflow handler when a step is being created.
1990
+ * Dehydrates values from within the workflow execution environment.
1991
+ */
1992
+ export async function dehydrateStepArguments(value, _runId, key, global = globalThis, v1Compat = false, compression = false) {
1993
+ if (v1Compat) {
1994
+ const str = stringify(value, getWorkflowReducers(global));
1995
+ return revive(str);
1996
+ }
1997
+ try {
1998
+ const compressionStats = {};
1999
+ const result = await stepModule.serialize(value, key, {
2000
+ global,
2001
+ extraReducers: getStreamAndRequestReducers(getWorkflowReducers(global)),
2002
+ compression,
2003
+ compressionStats,
1312
2004
  });
1313
- return obj;
2005
+ await recordCompression(compressionStats, 'serialize');
2006
+ return result;
2007
+ }
2008
+ catch (error) {
2009
+ const cause = unwrapSerializationCause(error);
2010
+ const { message, hint } = formatSerializationError('step arguments', cause);
2011
+ throw new SerializationError(message, { hint, cause });
1314
2012
  }
1315
- throw new Error(`Unsupported serialization format: ${format}`);
1316
2013
  }
1317
2014
  /**
1318
- * Dehydrate workflow return value for storage.
2015
+ * Called from the step handler to hydrate the arguments of a step
2016
+ * from the database at the start of the step execution.
2017
+ */
2018
+ export async function hydrateStepArguments(value, runId, key, ops = [], global = globalThis, extraRevivers = {}, deploymentId) {
2019
+ const compressionStats = {};
2020
+ const result = await stepModule.deserialize(value, key, {
2021
+ global,
2022
+ extraRevivers: {
2023
+ ...getStreamAndRequestRevivers(getStepRevivers(global, ops, runId, key, deploymentId)),
2024
+ ...extraRevivers,
2025
+ },
2026
+ compressionStats,
2027
+ });
2028
+ await recordCompression(compressionStats, 'deserialize');
2029
+ return result;
2030
+ }
2031
+ /**
2032
+ * Called from the step handler when a step has completed.
2033
+ * Dehydrates values from within the step execution environment
2034
+ * into a format that can be saved to the database.
1319
2035
  *
1320
2036
  * @param value - The value to serialize
1321
2037
  * @param runId - Run ID for encryption context
1322
2038
  * @param key - Encryption key (undefined to skip encryption)
2039
+ * @param ops - Promise array for stream operations
1323
2040
  * @param global - Global object for serialization context
2041
+ * @param v1Compat - Enable legacy v1 compatibility mode
2042
+ * @param framedByteStreams - Whether the target run can decode wire-framed
2043
+ * byte streams. Should match the target deployment's capability — see
2044
+ * `getRunCapabilities` in `capabilities.ts`. Defaults to `false` for
2045
+ * backwards compatibility with older runs.
1324
2046
  * @returns The dehydrated value as binary data (Uint8Array) with format prefix
1325
2047
  */
1326
- export async function dehydrateWorkflowReturnValue(value, _runId, key, global = globalThis, v1Compat = false) {
2048
+ export async function dehydrateStepReturnValue(value, runId, key, ops = [], global = globalThis, v1Compat = false, framedByteStreams = false, compression = false) {
2049
+ if (v1Compat) {
2050
+ const str = stringify(value, getStepReducers(global, ops, runId, key, framedByteStreams));
2051
+ return revive(str);
2052
+ }
1327
2053
  try {
1328
- const str = stringify(value, getWorkflowReducers(global));
1329
- if (v1Compat) {
1330
- return revive(str);
1331
- }
2054
+ const compressionStats = {};
2055
+ const result = await stepModule.serialize(value, key, {
2056
+ global,
2057
+ extraReducers: getStreamAndRequestReducers(getStepReducers(global, ops, runId, key, framedByteStreams)),
2058
+ compression,
2059
+ compressionStats,
2060
+ });
2061
+ await recordCompression(compressionStats, 'serialize');
2062
+ return result;
2063
+ }
2064
+ catch (error) {
2065
+ const cause = unwrapSerializationCause(error);
2066
+ const { message, hint } = formatSerializationError('step return value', cause);
2067
+ throw new SerializationError(message, { hint, cause });
2068
+ }
2069
+ }
2070
+ /**
2071
+ * Called from the step handler when a step throws. Dehydrates the thrown
2072
+ * value from within the step execution environment into a format that can
2073
+ * be saved to the database in a `step_failed` or `step_retrying` event.
2074
+ *
2075
+ * Any JavaScript value can be thrown (strings, numbers, objects, Errors,
2076
+ * Error subclasses), so the same serialization pipeline used for step
2077
+ * arguments and return values is applied here.
2078
+ *
2079
+ * @param value - The thrown value to serialize (can be any type)
2080
+ * @param runId - Run ID for encryption context
2081
+ * @param key - Encryption key (undefined to skip encryption)
2082
+ * @param ops - Promise array for stream operations
2083
+ * @param global - Global object for serialization context
2084
+ * @returns The dehydrated value as binary data (Uint8Array) with format prefix
2085
+ */
2086
+ export async function dehydrateStepError(value, runId, key, ops = [], global = globalThis, compression = false) {
2087
+ try {
2088
+ const str = stringify(value, getStepReducers(global, ops, runId, key));
1332
2089
  const payload = new TextEncoder().encode(str);
1333
2090
  const serialized = encodeWithFormatPrefix(SerializationFormat.DEVALUE_V1, payload);
1334
- // Encrypt if world supports encryption
1335
- return maybeEncrypt(serialized, key);
2091
+ // Compress before encrypting encrypted bytes don't compress.
2092
+ const compressionStats = {};
2093
+ const compressed = await compress(serialized, compression, compressionStats);
2094
+ const encrypted = (await maybeEncrypt(compressed, key));
2095
+ await recordCompression(compressionStats, 'serialize');
2096
+ return encrypted;
1336
2097
  }
1337
2098
  catch (error) {
1338
- throw new WorkflowRuntimeError(formatSerializationError('workflow return value', error), { slug: 'serialization-failed', cause: error });
2099
+ const cause = unwrapSerializationCause(error);
2100
+ const { message, hint } = formatSerializationError('step error', cause);
2101
+ throw new SerializationError(message, { hint, cause });
1339
2102
  }
1340
2103
  }
1341
2104
  /**
1342
- * Called from the client side (i.e. the execution environment where
1343
- * the workflow run was initiated from) to hydrate the workflow
1344
- * return value of a completed workflow run.
2105
+ * Called from the workflow handler when replaying the event log of a
2106
+ * `step_failed` or `step_retrying` event. Hydrates the thrown value from
2107
+ * the database so the workflow can see the original thrown value.
1345
2108
  *
1346
2109
  * @param value - Binary serialized data (Uint8Array) with format prefix
1347
2110
  * @param runId - Run ID for decryption context
1348
2111
  * @param key - Encryption key (undefined to skip decryption)
1349
- * @param ops - Promise array for stream operations
1350
2112
  * @param global - Global object for deserialization context
1351
2113
  * @param extraRevivers - Additional revivers for custom types
1352
- * @returns The hydrated return value, ready to be consumed by the client
2114
+ * @returns The hydrated thrown value, ready to reject the step promise
1353
2115
  */
1354
- export async function hydrateWorkflowReturnValue(value, runId, key, ops = [], global = globalThis, extraRevivers = {}) {
1355
- // Decrypt if needed
1356
- const decrypted = await maybeDecrypt(value, key);
1357
- // Legacy specVersion 1 runs stored data as plain JSON arrays (not binary).
1358
- // These pass through maybeDecrypt unchanged and are deserialized directly
1359
- // via devalue's unflatten().
2116
+ export async function hydrateStepError(value, _runId, key, global = globalThis, extraRevivers = {}) {
2117
+ const compressionStats = {};
2118
+ const decrypted = await decompress(await maybeDecrypt(value, key), compressionStats);
2119
+ await recordCompression(compressionStats, 'deserialize');
1360
2120
  if (!(decrypted instanceof Uint8Array)) {
2121
+ // Treated as a devalue "flattened" array. In production this branch is
2122
+ // exercised by legacy code paths that bypassed `dehydrateStepError`; the
2123
+ // SDK version is pinned per workflow run via skew protection, so a
2124
+ // current-version producer always emits a Uint8Array here. If a
2125
+ // misshapen value reaches us, `unflatten` throws — that's intentional:
2126
+ // the higher-level hydration helpers (`hydrateStepIO`,
2127
+ // `hydrateResourceIO`) already wrap us in a try/catch that leaves the
2128
+ // field un-hydrated for o11y display, and surfacing the throw to logs
2129
+ // is more debuggable than silently masking the unsupported shape.
1361
2130
  return unflatten(decrypted, {
1362
- ...getExternalRevivers(global, ops, runId, key),
2131
+ ...getWorkflowRevivers(global),
1363
2132
  ...extraRevivers,
1364
2133
  });
1365
2134
  }
1366
2135
  const { format, payload } = decodeFormatPrefix(decrypted);
1367
2136
  if (format === SerializationFormat.DEVALUE_V1) {
1368
2137
  const str = new TextDecoder().decode(payload);
1369
- const obj = parse(str, {
1370
- ...getExternalRevivers(global, ops, runId, key),
2138
+ return parse(str, {
2139
+ ...getWorkflowRevivers(global),
1371
2140
  ...extraRevivers,
1372
2141
  });
1373
- return obj;
1374
2142
  }
1375
2143
  throw new Error(`Unsupported serialization format: ${format}`);
1376
2144
  }
1377
2145
  /**
1378
- * Called from the workflow handler when a step is being created.
1379
- * Dehydrates values from within the workflow execution environment
1380
- * into a format that can be saved to the database.
2146
+ * Called from the workflow handler when the workflow itself throws.
2147
+ * Dehydrates the thrown value from within the workflow execution environment
2148
+ * into a format that can be saved to the database in a `run_failed` event.
1381
2149
  *
1382
- * @param value - The value to serialize
2150
+ * @param value - The thrown value to serialize (can be any type)
1383
2151
  * @param runId - Run ID for encryption context
1384
2152
  * @param key - Encryption key (undefined to skip encryption)
1385
2153
  * @param global - Global object for serialization context
1386
- * @param v1Compat - Enable legacy v1 compatibility mode
1387
2154
  * @returns The dehydrated value as binary data (Uint8Array) with format prefix
1388
2155
  */
1389
- export async function dehydrateStepArguments(value, _runId, key, global = globalThis, v1Compat = false) {
2156
+ export async function dehydrateRunError(value, _runId, key, global = globalThis, compression = false) {
1390
2157
  try {
1391
2158
  const str = stringify(value, getWorkflowReducers(global));
1392
- if (v1Compat) {
1393
- return revive(str);
1394
- }
1395
2159
  const payload = new TextEncoder().encode(str);
1396
2160
  const serialized = encodeWithFormatPrefix(SerializationFormat.DEVALUE_V1, payload);
1397
- // Encrypt if world supports encryption
1398
- return maybeEncrypt(serialized, key);
2161
+ // Compress before encrypting encrypted bytes don't compress.
2162
+ const compressionStats = {};
2163
+ const compressed = await compress(serialized, compression, compressionStats);
2164
+ const encrypted = (await maybeEncrypt(compressed, key));
2165
+ await recordCompression(compressionStats, 'serialize');
2166
+ return encrypted;
1399
2167
  }
1400
2168
  catch (error) {
1401
- throw new WorkflowRuntimeError(formatSerializationError('step arguments', error), { slug: 'serialization-failed', cause: error });
2169
+ const cause = unwrapSerializationCause(error);
2170
+ const { message, hint } = formatSerializationError('run error', cause);
2171
+ throw new SerializationError(message, { hint, cause });
1402
2172
  }
1403
2173
  }
1404
2174
  /**
1405
- * Called from the step handler to hydrate the arguments of a step
1406
- * from the database at the start of the step execution.
2175
+ * Called from the client side (or observability tools) to hydrate the run
2176
+ * error value of a failed workflow run.
1407
2177
  *
1408
2178
  * @param value - Binary serialized data (Uint8Array) with format prefix
1409
2179
  * @param runId - Run ID for decryption context
@@ -1411,59 +2181,33 @@ export async function dehydrateStepArguments(value, _runId, key, global = global
1411
2181
  * @param ops - Promise array for stream operations
1412
2182
  * @param global - Global object for deserialization context
1413
2183
  * @param extraRevivers - Additional revivers for custom types
1414
- * @returns The hydrated value, ready to be consumed by the step user-code function
2184
+ * @returns The hydrated thrown value, ready to be consumed by the client
1415
2185
  */
1416
- export async function hydrateStepArguments(value, runId, key, ops = [], global = globalThis, extraRevivers = {}) {
1417
- // Decrypt if needed
1418
- const decrypted = await maybeDecrypt(value, key);
1419
- // Legacy specVersion 1 runs stored data as plain JSON arrays (not binary).
1420
- // These pass through maybeDecrypt unchanged and are deserialized directly
1421
- // via devalue's unflatten().
2186
+ export async function hydrateRunError(value, runId, key, ops = [], global = globalThis, extraRevivers = {}) {
2187
+ const compressionStats = {};
2188
+ const decrypted = await decompress(await maybeDecrypt(value, key), compressionStats);
2189
+ await recordCompression(compressionStats, 'deserialize');
1422
2190
  if (!(decrypted instanceof Uint8Array)) {
2191
+ // See the matching note in `hydrateStepError`: this branch is for
2192
+ // devalue flattened arrays from legacy callers; current SDK versions
2193
+ // always emit a Uint8Array, and a misshapen value here intentionally
2194
+ // throws via `unflatten` so the surrounding try/catch in o11y helpers
2195
+ // surfaces the issue rather than masking it.
1423
2196
  return unflatten(decrypted, {
1424
- ...getStepRevivers(global, ops, runId, key),
2197
+ ...getExternalRevivers(global, ops, runId, key),
1425
2198
  ...extraRevivers,
1426
2199
  });
1427
2200
  }
1428
2201
  const { format, payload } = decodeFormatPrefix(decrypted);
1429
2202
  if (format === SerializationFormat.DEVALUE_V1) {
1430
2203
  const str = new TextDecoder().decode(payload);
1431
- const obj = parse(str, {
1432
- ...getStepRevivers(global, ops, runId, key),
2204
+ return parse(str, {
2205
+ ...getExternalRevivers(global, ops, runId, key),
1433
2206
  ...extraRevivers,
1434
2207
  });
1435
- return obj;
1436
2208
  }
1437
2209
  throw new Error(`Unsupported serialization format: ${format}`);
1438
2210
  }
1439
- /**
1440
- * Called from the step handler when a step has completed.
1441
- * Dehydrates values from within the step execution environment
1442
- * into a format that can be saved to the database.
1443
- *
1444
- * @param value - The value to serialize
1445
- * @param runId - Run ID for encryption context
1446
- * @param key - Encryption key (undefined to skip encryption)
1447
- * @param ops - Promise array for stream operations
1448
- * @param global - Global object for serialization context
1449
- * @param v1Compat - Enable legacy v1 compatibility mode
1450
- * @returns The dehydrated value as binary data (Uint8Array) with format prefix
1451
- */
1452
- export async function dehydrateStepReturnValue(value, runId, key, ops = [], global = globalThis, v1Compat = false) {
1453
- try {
1454
- const str = stringify(value, getStepReducers(global, ops, runId, key));
1455
- if (v1Compat) {
1456
- return revive(str);
1457
- }
1458
- const payload = new TextEncoder().encode(str);
1459
- const serialized = encodeWithFormatPrefix(SerializationFormat.DEVALUE_V1, payload);
1460
- // Encrypt if world supports encryption
1461
- return maybeEncrypt(serialized, key);
1462
- }
1463
- catch (error) {
1464
- throw new WorkflowRuntimeError(formatSerializationError('step return value', error), { slug: 'serialization-failed', cause: error });
1465
- }
1466
- }
1467
2211
  /**
1468
2212
  * Called from the workflow handler when replaying the event log of a `step_completed` event.
1469
2213
  * Hydrates the return value of a step from the database.
@@ -1473,28 +2217,56 @@ export async function dehydrateStepReturnValue(value, runId, key, ops = [], glob
1473
2217
  * @param key - Encryption key (undefined to skip decryption)
1474
2218
  * @param global - Global object for deserialization context
1475
2219
  * @param extraRevivers - Additional revivers for custom types
1476
- * @returns The hydrated return value of a step, ready to be consumed by the workflow handler
2220
+ * Called from the workflow handler when replaying the event log
2221
+ * of a `step_completed` event.
1477
2222
  */
1478
2223
  export async function hydrateStepReturnValue(value, _runId, key, global = globalThis, extraRevivers = {}) {
1479
- // Decrypt if needed
1480
- const decrypted = await maybeDecrypt(value, key);
1481
- // Legacy specVersion 1 runs stored data as plain JSON arrays (not binary).
1482
- // These pass through maybeDecrypt unchanged and are deserialized directly
1483
- // via devalue's unflatten().
1484
- if (!(decrypted instanceof Uint8Array)) {
1485
- return unflatten(decrypted, {
1486
- ...getWorkflowRevivers(global),
2224
+ const compressionStats = {};
2225
+ const inflated = await decompress(await maybeDecrypt(value, key), compressionStats);
2226
+ await recordCompression(compressionStats, 'deserialize');
2227
+ return workflowModule.deserialize(inflated, {
2228
+ global,
2229
+ extraRevivers: {
2230
+ ...getStreamAndRequestRevivers(getWorkflowRevivers(global)),
1487
2231
  ...extraRevivers,
1488
- });
2232
+ },
2233
+ });
2234
+ }
2235
+ // ---- Helpers to extract stream/Request/Response reducers and revivers ----
2236
+ // The mode-specific get*Reducers/get*Revivers functions return objects that
2237
+ // include both "common" entries (Date, Error, Map, etc.) and mode-specific
2238
+ // entries (ReadableStream, WritableStream, Request, Response, StepFunction).
2239
+ // The common entries are already composed by the codec. We only need to
2240
+ // pass through the mode-specific entries as extraReducers/extraRevivers.
2241
+ const STREAM_AND_REQUEST_KEYS = [
2242
+ 'ReadableStream',
2243
+ 'WritableStream',
2244
+ 'Request',
2245
+ 'Response',
2246
+ 'StepFunction',
2247
+ // Wire AbortController/AbortSignal through the client serialization path so
2248
+ // signals reachable via Request.signal (or as direct arguments) get their
2249
+ // dedicated reducer. Without this, devalue falls back to its arbitrary-POJO
2250
+ // path and fails for any signal the Request reducer forwards.
2251
+ 'AbortController',
2252
+ 'AbortSignal',
2253
+ ];
2254
+ function getStreamAndRequestReducers(allReducers) {
2255
+ const extra = {};
2256
+ for (const key of STREAM_AND_REQUEST_KEYS) {
2257
+ if (key in allReducers) {
2258
+ extra[key] = allReducers[key];
2259
+ }
1489
2260
  }
1490
- const { format, payload } = decodeFormatPrefix(decrypted);
1491
- if (format === SerializationFormat.DEVALUE_V1) {
1492
- const str = new TextDecoder().decode(payload);
1493
- return parse(str, {
1494
- ...getWorkflowRevivers(global),
1495
- ...extraRevivers,
1496
- });
2261
+ return extra;
2262
+ }
2263
+ function getStreamAndRequestRevivers(allRevivers) {
2264
+ const extra = {};
2265
+ for (const key of STREAM_AND_REQUEST_KEYS) {
2266
+ if (key in allRevivers) {
2267
+ extra[key] = allRevivers[key];
2268
+ }
1497
2269
  }
1498
- throw new Error(`Unsupported serialization format: ${format}`);
2270
+ return extra;
1499
2271
  }
1500
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VyaWFsaXphdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9zZXJpYWxpemF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDbEMsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDeEQsT0FBTyxFQUFFLG9CQUFvQixFQUFFLGtCQUFrQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDM0UsT0FBTyxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUNwRSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDeEMsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDakUsT0FBTyxFQUNMLE9BQU8sSUFBSSxhQUFhLEVBQ3hCLE9BQU8sSUFBSSxhQUFhLEdBRXpCLE1BQU0saUJBQWlCLENBQUM7QUFhekIsT0FBTyxFQUNMLG9CQUFvQixFQUNwQixhQUFhLEVBQ2IsZ0JBQWdCLEVBQ2hCLGdCQUFnQixHQUNqQixNQUFNLHVCQUF1QixDQUFDO0FBQy9CLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDNUMsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUMvQyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDOUMsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQzNELE9BQU8sRUFDTCxnQkFBZ0IsRUFDaEIsV0FBVyxFQUNYLGtCQUFrQixFQUNsQixrQkFBa0IsRUFDbEIseUJBQXlCLEdBQzFCLE1BQU0sY0FBYyxDQUFDO0FBRXRCLCtFQUErRTtBQUMvRSxxQ0FBcUM7QUFDckMsK0VBQStFO0FBQy9FLEVBQUU7QUFDRiw0RUFBNEU7QUFD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OlsiaW1wb3J0IHsgdHlwZXMgfSBmcm9tICdub2RlOnV0aWwnO1xuaW1wb3J0IHsgV29ya2Zsb3dSdW50aW1lRXJyb3IgfSBmcm9tICdAd29ya2Zsb3cvZXJyb3JzJztcbmltcG9ydCB7IFdPUktGTE9XX0RFU0VSSUFMSVpFLCBXT1JLRkxPV19TRVJJQUxJWkUgfSBmcm9tICdAd29ya2Zsb3cvc2VyZGUnO1xuaW1wb3J0IHsgRGV2YWx1ZUVycm9yLCBwYXJzZSwgc3RyaW5naWZ5LCB1bmZsYXR0ZW4gfSBmcm9tICdkZXZhbHVlJztcbmltcG9ydCB7IG1vbm90b25pY0ZhY3RvcnkgfSBmcm9tICd1bGlkJztcbmltcG9ydCB7IGdldFNlcmlhbGl6YXRpb25DbGFzcyB9IGZyb20gJy4vY2xhc3Mtc2VyaWFsaXphdGlvbi5qcyc7XG5pbXBvcnQge1xuICBkZWNyeXB0IGFzIGFlc0djbURlY3J5cHQsXG4gIGVuY3J5cHQgYXMgYWVzR2NtRW5jcnlwdCxcbiAgdHlwZSBDcnlwdG9LZXksXG59IGZyb20gJy4vZW5jcnlwdGlvbi5qcyc7XG5cbi8qKlxuICogRW5jcnlwdGlvbiBrZXkgcGFyYW1ldGVyIHR5cGUuIEFjY2VwdHMgYSByZXNvbHZlZCBrZXksIHVuZGVmaW5lZCAobm8gZW5jcnlwdGlvbiksXG4gKiBvciBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBlaXRoZXIuIFRoaXMgYWxsb3dzIHN5bmNocm9ub3VzIGZ1bmN0aW9uIHNpZ25hdHVyZXNcbiAqIChlLmcuLCBnZXRSZWFkYWJsZSgpKSB0byB0aHJlYWQgdGhlIGtleSB0aHJvdWdoIHdpdGhvdXQgYXdhaXRpbmcgaXQg4oCUIHRoZSBwcm9taXNlXG4gKiBpcyByZXNvbHZlZCBsYXppbHkgaW5zaWRlIHRoZSBmaXJzdCBhc3luYyB0cmFuc2Zvcm0oKSBjYWxsLlxuICovXG5leHBvcnQgdHlwZSBFbmNyeXB0aW9uS2V5UGFyYW0gPVxuICB8IENyeXB0b0tleVxuICB8IHVuZGVmaW5lZFxuICB8IFByb21pc2U8Q3J5cHRvS2V5IHwgdW5kZWZpbmVkPjtcblxuaW1wb3J0IHtcbiAgY3JlYXRlRmx1c2hhYmxlU3RhdGUsXG4gIGZsdXNoYWJsZVBpcGUsXG4gIHBvbGxSZWFkYWJsZUxvY2ssXG4gIHBvbGxXcml0YWJsZUxvY2ssXG59IGZyb20gJy4vZmx1c2hhYmxlLXN0cmVhbS5qcyc7XG5pbXBvcnQgeyBydW50aW1lTG9nZ2VyIH0gZnJvbSAnLi9sb2dnZXIuanMnO1xuaW1wb3J0IHsgZ2V0U3RlcEZ1bmN0aW9uIH0gZnJvbSAnLi9wcml2YXRlLmpzJztcbmltcG9ydCB7IGdldFdvcmxkIH0gZnJvbSAnLi9ydW50aW1lL3dvcmxkLmpzJztcbmltcG9ydCB7IGNvbnRleHRTdG9yYWdlIH0gZnJvbSAnLi9zdGVwL2NvbnRleHQtc3RvcmFnZS5qcyc7XG5pbXBvcnQge1xuICBCT0RZX0lOSVRfU1lNQk9MLFxuICBTVEFCTEVfVUxJRCxcbiAgU1RSRUFNX05BTUVfU1lNQk9MLFxuICBTVFJFQU1fVFlQRV9TWU1CT0wsXG4gIFdFQkhPT0tfUkVTUE9OU0VfV1JJVEFCTEUsXG59IGZyb20gJy4vc3ltYm9scy5qcyc7XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFNlcmlhbGl6YXRpb24gRm9ybWF0IFByZWZpeCBTeXN0ZW1cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vXG4vLyBBbGwgc2VyaWFsaXplZCBwYXlsb2FkcyBhcmUgcHJlZml4ZWQgd2l0aCBhIDQtYnl0ZSBmb3JtYXQgaWRlbnRpZmllciB0aGF0XG4vLyBhbGxvd3MgdGhlIGNsaWVudCB0byBkZXRlcm1pbmUgaG93IHRvIGRlY29kZSB0aGUgcGF5bG9hZC4gVGhpcyBlbmFibGVzOlxuLy9cbi8vIDEuIFNlbGYtZGVzY3JpYmluZyBwYXlsb2FkcyAtIFRoZSBXb3JsZCBsYXllciBpcyBhZ25vc3RpYyB0byBzZXJpYWxpemF0aW9uIGZvcm1hdFxuLy8gMi4gR3JhZHVhbCBtaWdyYXRpb24gLSBPbGQgcnVucyBrZWVwIHdvcmtpbmcsIG5ldyBydW5zIGNhbiB1c2UgbmV3IGZvcm1hdHNcbi8vIDMuIENvbXBvc2FiaWxpdHkgLSBFbmNyeXB0aW9uIGNhbiB3cmFwIGFueSBmb3JtYXQgKGUuZy4sIFwiZW5jclwiIHdyYXBwaW5nIFwiZGV2bFwiKVxuLy8gNC4gRGVidWdnaW5nIC0gUmF3IGRhdGEgaW5zcGVjdGlvbiBpbW1lZGlhdGVseSByZXZlYWxzIHRoZSBmb3JtYXRcbi8vXG4vLyBGb3JtYXQ6IFs0IGJ5dGVzOiBmb3JtYXQgaWRlbnRpZmllcl1bcGF5bG9hZF1cbi8vXG4vLyBUaGUgNC1jaGFyYWN0ZXIgcHJlZml4IGNvbnZlbnRpb24gbWF0Y2hlcyBvdGhlciB3b3JrZmxvdyBJRHMgKHdydW4sIHN0ZXAsIHdhaXQsIGV0Yy4pXG4vL1xuLy8gQ3VycmVudCBmb3JtYXRzOlxuLy8gLSBcImRldmxcIiAtIGRldmFsdWUgc3RyaW5naWZ5L3BhcnNlIHdpdGggVGV4dEVuY29kZXIvVGV4dERlY29kZXIgKGN1cnJlbnQgZGVmYXVsdClcbi8vIC0gXCJlbmNyXCIgLSBFbmNyeXB0ZWQgcGF5bG9hZCAoaW5uZXIgcGF5bG9hZCBoYXMgaXRzIG93biBmb3JtYXQgcHJlZml4KVxuLy9cbi8vIEZ1dHVyZSBmb3JtYXRzIChyZXNlcnZlZCk6XG4vLyAtIFwiY2JvclwiIC0gQ0JPUiBiaW5hcnkgc2VyaWFsaXphdGlvblxuXG4vKipcbiAqIEtub3duIHNlcmlhbGl6YXRpb24gZm9ybWF0IGlkZW50aWZpZXJzLlxuICogRWFjaCBmb3JtYXQgSUQgaXMgZXhhY3RseSA0IEFTQ0lJIGNoYXJhY3RlcnMsIG1hdGNoaW5nIHRoZSBjb252ZW50aW9uXG4gKiB1c2VkIGZvciBvdGhlciB3b3JrZmxvdyBJRHMgKHdydW4sIHN0ZXAsIHdhaXQsIGV0Yy4pXG4gKi9cbmV4cG9ydCBjb25zdCBTZXJpYWxpemF0aW9uRm9ybWF0ID0ge1xuICAvKiogZGV2YWx1ZSBzdHJpbmdpZnkvcGFyc2Ugd2l0aCBUZXh0RW5jb2Rlci9UZXh0RGVjb2RlciAqL1xuICBERVZBTFVFX1YxOiAnZGV2bCcsXG4gIC8qKiBFbmNyeXB0ZWQgcGF5bG9hZCAoaW5uZXIgcGF5bG9hZCBoYXMgaXRzIG93biBmb3JtYXQgcHJlZml4KSAqL1xuICBFTkNSWVBURUQ6ICdlbmNyJyxcbn0gYXMgY29uc3Q7XG5cbmV4cG9ydCB0eXBlIFNlcmlhbGl6YXRpb25Gb3JtYXRUeXBlID1cbiAgKHR5cGVvZiBTZXJpYWxpemF0aW9uRm9ybWF0KVtrZXlvZiB0eXBlb2YgU2VyaWFsaXphdGlvbkZvcm1hdF07XG5cbi8qKiBMZW5ndGggb2YgdGhlIGZvcm1hdCBwcmVmaXggaW4gYnl0ZXMgKi9cbmNvbnN0IEZPUk1BVF9QUkVGSVhfTEVOR1RIID0gNDtcblxuLyoqIFRleHRFbmNvZGVyIGluc3RhbmNlIGZvciBmb3JtYXQgcHJlZml4IGVuY29kaW5nICovXG5jb25zdCBmb3JtYXRFbmNvZGVyID0gbmV3IFRleHRFbmNvZGVyKCk7XG5cbi8qKiBUZXh0RGVjb2RlciBpbnN0YW5jZSBmb3IgZm9ybWF0IHByZWZpeCBkZWNvZGluZyAqL1xuY29uc3QgZm9ybWF0RGVjb2RlciA9IG5ldyBUZXh0RGVjb2RlcigpO1xuXG4vKipcbiAqIEVuY29kZSBhIHBheWxvYWQgd2l0aCBhIGZvcm1hdCBwcmVmaXguXG4gKlxuICogQHBhcmFtIGZvcm1hdCAtIFRoZSBmb3JtYXQgaWRlbnRpZmllciAobXVzdCBiZSBleGFjdGx5IDQgQVNDSUkgY2hhcmFjdGVycylcbiAqIEBwYXJhbSBwYXlsb2FkIC0gVGhlIHNlcmlhbGl6ZWQgcGF5bG9hZCBieXRlc1xuICogQHJldHVybnMgQSBuZXcgVWludDhBcnJheSB3aXRoIGZvcm1hdCBwcmVmaXggcHJlcGVuZGVkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlbmNvZGVXaXRoRm9ybWF0UHJlZml4KFxuICBmb3JtYXQ6IFNlcmlhbGl6YXRpb25Gb3JtYXRUeXBlLFxuICBwYXlsb2FkOiBVaW50OEFycmF5IHwgdW5rbm93blxuKTogVWludDhBcnJheSB8IHVua25vd24ge1xuICBpZiAoIShwYXlsb2FkIGluc3RhbmNlb2YgVWludDhBcnJheSkpIHtcbiAgICByZXR1cm4gcGF5bG9hZDtcbiAgfVxuXG4gIGNvbnN0IHByZWZpeEJ5dGVzID0gZm9ybWF0RW5jb2Rlci5lbmNvZGUoZm9ybWF0KTtcbiAgaWYgKHByZWZpeEJ5dGVzLmxlbmd0aCAhPT0gRk9STUFUX1BSRUZJWF9MRU5HVEgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgRm9ybWF0IGlkZW50aWZpZXIgbXVzdCBiZSBleGFjdGx5ICR7Rk9STUFUX1BSRUZJWF9MRU5HVEh9IEFTQ0lJIGNoYXJhY3RlcnMsIGdvdCBcIiR7Zm9ybWF0fVwiICgke3ByZWZpeEJ5dGVzLmxlbmd0aH0gYnl0ZXMpYFxuICAgICk7XG4gIH1cblxuICBjb25zdCByZXN1bHQgPSBuZXcgVWludDhBcnJheShGT1JNQVRfUFJFRklYX0xFTkdUSCArIHBheWxvYWQubGVuZ3RoKTtcbiAgcmVzdWx0LnNldChwcmVmaXhCeXRlcywgMCk7XG4gIHJlc3VsdC5zZXQocGF5bG9hZCwgRk9STUFUX1BSRUZJWF9MRU5HVEgpO1xuICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKipcbiAqIFBlZWsgYXQgdGhlIGZvcm1hdCBwcmVmaXggd2l0aG91dCBjb25zdW1pbmcgaXQuXG4gKiBVc2VmdWwgZm9yIGNoZWNraW5nIGlmIGRhdGEgaXMgZW5jcnlwdGVkIGJlZm9yZSBkZWNpZGluZyBob3cgdG8gcHJvY2VzcyBpdC5cbiAqXG4gKiBAcGFyYW0gZGF0YSAtIFRoZSBmb3JtYXQtcHJlZml4ZWQgZGF0YVxuICogQHJldHVybnMgVGhlIGZvcm1hdCBpZGVudGlmaWVyLCBvciBudWxsIGlmIGRhdGEgaXMgbGVnYWN5L25vbi1iaW5hcnlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBlZWtGb3JtYXRQcmVmaXgoXG4gIGRhdGE6IFVpbnQ4QXJyYXkgfCB1bmtub3duXG4pOiBTZXJpYWxpemF0aW9uRm9ybWF0VHlwZSB8IG51bGwge1xuICBpZiAoIShkYXRhIGluc3RhbmNlb2YgVWludDhBcnJheSkgfHwgZGF0YS5sZW5ndGggPCBGT1JNQVRfUFJFRklYX0xFTkdUSCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIGNvbnN0IHByZWZpeEJ5dGVzID0gZGF0YS5zdWJhcnJheSgwLCBGT1JNQVRfUFJFRklYX0xFTkdUSCk7XG4gIGNvbnN0IGZvcm1hdCA9IGZvcm1hdERlY29kZXIuZGVjb2RlKHByZWZpeEJ5dGVzKTtcbiAgY29uc3Qga25vd25Gb3JtYXRzID0gT2JqZWN0LnZhbHVlcyhTZXJpYWxpemF0aW9uRm9ybWF0KSBhcyBzdHJpbmdbXTtcbiAgaWYgKCFrbm93bkZvcm1hdHMuaW5jbHVkZXMoZm9ybWF0KSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIHJldHVybiBmb3JtYXQgYXMgU2VyaWFsaXphdGlvbkZvcm1hdFR5cGU7XG59XG5cbi8qKlxuICogQ2hlY2sgaWYgZGF0YSBpcyBlbmNyeXB0ZWQgKGhhcyAnZW5jcicgZm9ybWF0IHByZWZpeCkuXG4gKlxuICogQHBhcmFtIGRhdGEgLSBUaGUgZm9ybWF0LXByZWZpeGVkIGRhdGFcbiAqIEByZXR1cm5zIHRydWUgaWYgZGF0YSBoYXMgdGhlIGVuY3J5cHRlZCBmb3JtYXQgcHJlZml4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0VuY3J5cHRlZChkYXRhOiBVaW50OEFycmF5IHwgdW5rbm93bik6IGJvb2xlYW4ge1xuICByZXR1cm4gcGVla0Zvcm1hdFByZWZpeChkYXRhKSA9PT0gU2VyaWFsaXphdGlvbkZvcm1hdC5FTkNSWVBURUQ7XG59XG5cbi8qKlxuICogRGVjb2RlIGEgZm9ybWF0LXByZWZpeGVkIHBheWxvYWQuXG4gKlxuICogQHBhcmFtIGRhdGEgLSBUaGUgZm9ybWF0LXByZWZpeGVkIGRhdGFcbiAqIEByZXR1cm5zIEFuIG9iamVjdCB3aXRoIHRoZSBmb3JtYXQgaWRlbnRpZmllciBhbmQgcGF5bG9hZFxuICogQHRocm93cyBFcnJvciBpZiB0aGUgZGF0YSBpcyB0b28gc2hvcnQgb3IgaGFzIGFuIHVua25vd24gZm9ybWF0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGVGb3JtYXRQcmVmaXgoZGF0YTogVWludDhBcnJheSB8IHVua25vd24pOiB7XG4gIGZvcm1hdDogU2VyaWFsaXphdGlvbkZvcm1hdFR5cGU7XG4gIHBheWxvYWQ6IFVpbnQ4QXJyYXk7XG59IHtcbiAgLy8gQ29tcGF0IGZvciBsZWdhY3kgc3BlY1ZlcnNpb24gMSBydW5zIHRoYXQgZG9uJ3QgaGF2ZSBhIGZvcm1hdCBwcmVmaXgsXG4gIC8vIGFuZCBkb24ndCBoYXZlIGEgYmluYXJ5IHBheWxvYWRcbiAgaWYgKCEoZGF0YSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGZvcm1hdDogU2VyaWFsaXphdGlvbkZvcm1hdC5ERVZBTFVFX1YxLFxuICAgICAgcGF5bG9hZDogbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKEpTT04uc3RyaW5naWZ5KGRhdGEpKSxcbiAgICB9O1xuICB9XG5cbiAgaWYgKGRhdGEubGVuZ3RoIDwgRk9STUFUX1BSRUZJWF9MRU5HVEgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgRGF0YSB0b28gc2hvcnQgdG8gY29udGFpbiBmb3JtYXQgcHJlZml4OiBleHBlY3RlZCBhdCBsZWFzdCAke0ZPUk1BVF9QUkVGSVhfTEVOR1RIfSBieXRlcywgZ290ICR7ZGF0YS5sZW5ndGh9YFxuICAgICk7XG4gIH1cblxuICBjb25zdCBwcmVmaXhCeXRlcyA9IGRhdGEuc3ViYXJyYXkoMCwgRk9STUFUX1BSRUZJWF9MRU5HVEgpO1xuICBjb25zdCBmb3JtYXQgPSBmb3JtYXREZWNvZGVyLmRlY29kZShwcmVmaXhCeXRlcyk7XG5cbiAgLy8gVmFsaWRhdGUgdGhlIGZvcm1hdCBpcyBrbm93blxuICBjb25zdCBrbm93bkZvcm1hdHMgPSBPYmplY3QudmFsdWVzKFNlcmlhbGl6YXRpb25Gb3JtYXQpIGFzIHN0cmluZ1tdO1xuICBpZiAoIWtub3duRm9ybWF0cy5pbmNsdWRlcyhmb3JtYXQpKSB7XG4gICAgdGhyb3cgbmV3IFdvcmtmbG93UnVudGltZUVycm9yKFxuICAgICAgYFVua25vd24gc2VyaWFsaXphdGlvbiBmb3JtYXQ6IFwiJHtmb3JtYXR9XCIuIEtub3duIGZvcm1hdHM6ICR7a25vd25Gb3JtYXRzLmpvaW4oJywgJyl9YFxuICAgICk7XG4gIH1cblxuICBjb25zdCBwYXlsb2FkID0gZGF0YS5zdWJhcnJheShGT1JNQVRfUFJFRklYX0xFTkdUSCk7XG4gIHJldHVybiB7IGZvcm1hdDogZm9ybWF0IGFzIFNlcmlhbGl6YXRpb25Gb3JtYXRUeXBlLCBwYXlsb2FkIH07XG59XG5cbi8qKlxuICogRGVmYXVsdCBVTElEIGdlbmVyYXRvciBmb3IgY29udGV4dHMgd2hlcmUgVk0ncyBzZWVkZWQgYHN0YWJsZVVsaWRgIGlzbid0IGF2YWlsYWJsZS5cbiAqIFVzZWQgYXMgYSBmYWxsYmFjayB3aGVuIHNlcmlhbGl6aW5nIHN0cmVhbXMgb3V0c2lkZSB0aGUgd29ya2Zsb3cgVk0gY29udGV4dFxuICogKGUuZy4sIHdoZW4gc3RhcnRpbmcgYSB3b3JrZmxvdyBvciBoYW5kbGluZyBzdGVwIHJldHVybiB2YWx1ZXMpLlxuICovXG5jb25zdCBkZWZhdWx0VWxpZCA9IG1vbm90b25pY0ZhY3RvcnkoKTtcblxuLyoqXG4gKiBGb3JtYXQgYSBzZXJpYWxpemF0aW9uIGVycm9yIHdpdGggY29udGV4dCBhYm91dCB3aGF0IGZhaWxlZC5cbiAqIEV4dHJhY3RzIHBhdGgsIHZhbHVlLCBhbmQgcmVhc29uIGZyb20gZGV2YWx1ZSdzIERldmFsdWVFcnJvciB3aGVuIGF2YWlsYWJsZS5cbiAqIExvZ3MgdGhlIHByb2JsZW1hdGljIHZhbHVlIHRvIHRoZSBjb25zb2xlIGZvciBiZXR0ZXIgZGVidWdnaW5nLlxuICovXG5mdW5jdGlvbiBmb3JtYXRTZXJpYWxpemF0aW9uRXJyb3IoY29udGV4dDogc3RyaW5nLCBlcnJvcjogdW5rbm93bik6IHN0cmluZyB7XG4gIC8vIFVzZSBcInJldHVybmluZ1wiIGZvciByZXR1cm4gdmFsdWVzLCBcInBhc3NpbmdcIiBmb3IgYXJndW1lbnRzL2lucHV0c1xuICBjb25zdCB2ZXJiID0gY29udGV4dC5pbmNsdWRlcygncmV0dXJuIHZhbHVlJykgPyAncmV0dXJuaW5nJyA6ICdwYXNzaW5nJztcblxuICAvLyBCdWlsZCB0aGUgZXJyb3IgbWVzc2FnZSB3aXRoIHBhdGggaW5mbyBpZiBhdmFpbGFibGUgZnJvbSBEZXZhbHVlRXJyb3JcbiAgbGV0IG1lc3NhZ2UgPSBgRmFpbGVkIHRvIHNlcmlhbGl6ZSAke2NvbnRleHR9YDtcbiAgaWYgKGVycm9yIGluc3RhbmNlb2YgRGV2YWx1ZUVycm9yICYmIGVycm9yLnBhdGgpIHtcbiAgICBtZXNzYWdlICs9IGAgYXQgcGF0aCBcIiR7ZXJyb3IucGF0aH1cImA7XG4gIH1cbiAgbWVzc2FnZSArPSBgLiBFbnN1cmUgeW91J3JlICR7dmVyYn0gc2VyaWFsaXphYmxlIHR5cGVzIChwbGFpbiBvYmplY3RzLCBhcnJheXMsIHByaW1pdGl2ZXMsIERhdGUsIFJlZ0V4cCwgTWFwLCBTZXQpLmA7XG5cbiAgLy8gTG9nIHRoZSBwcm9ibGVtYXRpYyB2YWx1ZSBmb3IgZGVidWdnaW5nXG4gIGlmIChlcnJvciBpbnN0YW5jZW9mIERldmFsdWVFcnJvciAmJiBlcnJvci52YWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgcnVudGltZUxvZ2dlci5lcnJvcignU2VyaWFsaXphdGlvbiBmYWlsZWQnLCB7XG4gICAgICBjb250ZXh0LFxuICAgICAgcHJvYmxlbWF0aWNWYWx1ZTogZXJyb3IudmFsdWUsXG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gbWVzc2FnZTtcbn1cblxuLyoqXG4gKiBEZXRlY3QgaWYgYSByZWFkYWJsZSBzdHJlYW0gaXMgYSBieXRlIHN0cmVhbS5cbiAqXG4gKiBAcGFyYW0gc3RyZWFtXG4gKiBAcmV0dXJucyBgXCJieXRlc1wiYCBpZiB0aGUgc3RyZWFtIGlzIGEgYnl0ZSBzdHJlYW0sIGB1bmRlZmluZWRgIG90aGVyd2lzZVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0U3RyZWFtVHlwZShzdHJlYW06IFJlYWRhYmxlU3RyZWFtKTogJ2J5dGVzJyB8IHVuZGVmaW5lZCB7XG4gIHRyeSB7XG4gICAgY29uc3QgcmVhZGVyID0gc3RyZWFtLmdldFJlYWRlcih7IG1vZGU6ICdieW9iJyB9KTtcbiAgICByZWFkZXIucmVsZWFzZUxvY2soKTtcbiAgICByZXR1cm4gJ2J5dGVzJztcbiAgfSBjYXRjaCB7fVxufVxuXG4vKipcbiAqIEZyYW1lIGZvcm1hdCBmb3Igc3RyZWFtIGNodW5rczpcbiAqICAgWzQtYnl0ZSBiaWctZW5kaWFuIGxlbmd0aF1bZm9ybWF0LXByZWZpeGVkIHBheWxvYWRdXG4gKlxuICogRWFjaCBjaHVuayBpcyBpbmRlcGVuZGVudGx5IGZyYW1lZCBzbyB0aGUgZGVzZXJpYWxpemVyIGNhbiBmaW5kXG4gKiBjaHVuayBib3VuZGFyaWVzIGV2ZW4gd2hlbiBtdWx0aXBsZSBjaHVua3MgYXJlIGNvbmNhdGVuYXRlZCBvclxuICogc3BsaXQgYWNyb3NzIHRyYW5zcG9ydCByZWFkcy5cbiAqL1xuY29uc3QgRlJBTUVfSEVBREVSX1NJWkUgPSA0O1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0U2VyaWFsaXplU3RyZWFtKFxuICByZWR1Y2VyczogUmVkdWNlcnMsXG4gIGNyeXB0b0tleTogRW5jcnlwdGlvbktleVBhcmFtXG4pOiBUcmFuc2Zvcm1TdHJlYW08YW55LCBVaW50OEFycmF5PiB7XG4gIGNvbnN0IGVuY29kZXIgPSBuZXcgVGV4dEVuY29kZXIoKTtcbiAgLy8gUmVzb2x2ZSB0aGUga2V5IHByb21pc2Ugb25jZSBvbiBmaXJzdCB1c2UgYW5kIGNhY2hlIHRoZSByZXN1bHQuXG4gIC8vIE5vdGU6IGlmIHRoZSBjcnlwdG9LZXkgcHJvbWlzZSByZWplY3RzIChlLmcuLCBuZXR3b3JrIGVycm9yIGZldGNoaW5nXG4gIC8vIHRoZSBkZXJpdmVkIGtleSksIHRoZSByZWplY3Rpb24gd29uJ3Qgc3VyZmFjZSB1bnRpbCB0aGUgZmlyc3QgY2h1bmtcbiAgLy8gaXMgcHJvY2Vzc2VkIOKAlCBub3QgYXQgc3RyZWFtIGNvbnN0cnVjdGlvbiB0aW1lLlxuICBjb25zdCBrZXlTdGF0ZSA9IHsgcmVzb2x2ZWQ6IGZhbHNlLCBrZXk6IHVuZGVmaW5lZCBhcyBDcnlwdG9LZXkgfCB1bmRlZmluZWQgfTtcbiAgY29uc3Qgc3RyZWFtID0gbmV3IFRyYW5zZm9ybVN0cmVhbTxhbnksIFVpbnQ4QXJyYXk+KHtcbiAgICBhc3luYyB0cmFuc2Zvcm0oY2h1bmssIGNvbnRyb2xsZXIpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGlmICgha2V5U3RhdGUucmVzb2x2ZWQpIHtcbiAgICAgICAgICBrZXlTdGF0ZS5rZXkgPSBhd2FpdCBjcnlwdG9LZXk7XG4gICAgICAgICAga2V5U3RhdGUucmVzb2x2ZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSBzdHJpbmdpZnkoY2h1bmssIHJlZHVjZXJzKTtcbiAgICAgICAgY29uc3QgcGF5bG9hZCA9IGVuY29kZXIuZW5jb2RlKHNlcmlhbGl6ZWQpO1xuICAgICAgICBsZXQgcHJlZml4ZWQgPSBlbmNvZGVXaXRoRm9ybWF0UHJlZml4KFxuICAgICAgICAgIFNlcmlhbGl6YXRpb25Gb3JtYXQuREVWQUxVRV9WMSxcbiAgICAgICAgICBwYXlsb2FkXG4gICAgICAgICkgYXMgVWludDhBcnJheTtcblxuICAgICAgICAvLyBFbmNyeXB0IHRoZSBmcmFtZSBwYXlsb2FkIGlmIGEga2V5IGlzIHByb3ZpZGVkLlxuICAgICAgICAvLyBUaGUgbGVuZ3RoIGhlYWRlciByZW1haW5zIGluIHRoZSBjbGVhciBzbyB0aGUgZGVzZXJpYWxpemVyIGNhblxuICAgICAgICAvLyBmaW5kIGZyYW1lIGJvdW5kYXJpZXMgcmVnYXJkbGVzcyBvZiB0cmFuc3BvcnQgY2h1bmtpbmcuXG4gICAgICAgIGlmIChrZXlTdGF0ZS5rZXkpIHtcbiAgICAgICAgICBjb25zdCBlbmNyeXB0ZWQgPSBhd2FpdCBhZXNHY21FbmNyeXB0KGtleVN0YXRlLmtleSwgcHJlZml4ZWQpO1xuICAgICAgICAgIHByZWZpeGVkID0gZW5jb2RlV2l0aEZvcm1hdFByZWZpeChcbiAgICAgICAgICAgIFNlcmlhbGl6YXRpb25Gb3JtYXQuRU5DUllQVEVELFxuICAgICAgICAgICAgZW5jcnlwdGVkXG4gICAgICAgICAgKSBhcyBVaW50OEFycmF5O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gV3JpdGUgbGVuZ3RoLXByZWZpeGVkIGZyYW1lOiBbNC1ieXRlIGxlbmd0aF1bcHJlZml4ZWQgZGF0YV1cbiAgICAgICAgY29uc3QgZnJhbWUgPSBuZXcgVWludDhBcnJheShGUkFNRV9IRUFERVJfU0laRSArIHByZWZpeGVkLmxlbmd0aCk7XG4gICAgICAgIG5ldyBEYXRhVmlldyhmcmFtZS5idWZmZXIpLnNldFVpbnQzMigwLCBwcmVmaXhlZC5sZW5ndGgsIGZhbHNlKTtcbiAgICAgICAgZnJhbWUuc2V0KHByZWZpeGVkLCBGUkFNRV9IRUFERVJfU0laRSk7XG4gICAgICAgIGNvbnRyb2xsZXIuZW5xdWV1ZShmcmFtZSk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBjb250cm9sbGVyLmVycm9yKFxuICAgICAgICAgIG5ldyBXb3JrZmxvd1J1bnRpbWVFcnJvcihcbiAgICAgICAgICAgIGZvcm1hdFNlcmlhbGl6YXRpb25FcnJvcignc3RyZWFtIGNodW5rJywgZXJyb3IpLFxuICAgICAgICAgICAgeyBzbHVnOiAnc2VyaWFsaXphdGlvbi1mYWlsZWQnLCBjYXVzZTogZXJyb3IgfVxuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9LFxuICB9KTtcbiAgcmV0dXJuIHN0cmVhbTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldERlc2VyaWFsaXplU3RyZWFtKFxuICByZXZpdmVyczogUmV2aXZlcnMsXG4gIGNyeXB0b0tleTogRW5jcnlwdGlvbktleVBhcmFtXG4pOiBUcmFuc2Zvcm1TdHJlYW08VWludDhBcnJheSwgYW55PiB7XG4gIGNvbnN0IGRlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoKTtcbiAgbGV0IGJ1ZmZlciA9IG5ldyBVaW50OEFycmF5KDApO1xuICAvLyBSZXNvbHZlIHRoZSBrZXkgcHJvbWlzZSBvbmNlIG9uIGZpcnN0IHVzZSBhbmQgY2FjaGUgdGhlIHJlc3VsdC5cbiAgY29uc3Qga2V5U3RhdGUgPSB7IHJlc29sdmVkOiBmYWxzZSwga2V5OiB1bmRlZmluZWQgYXMgQ3J5cHRvS2V5IHwgdW5kZWZpbmVkIH07XG5cbiAgZnVuY3Rpb24gYXBwZW5kVG9CdWZmZXIoZGF0YTogVWludDhBcnJheSkge1xuICAgIGNvbnN0IG5ld0J1ZmZlciA9IG5ldyBVaW50OEFycmF5KGJ1ZmZlci5sZW5ndGggKyBkYXRhLmxlbmd0aCk7XG4gICAgbmV3QnVmZmVyLnNldChidWZmZXIsIDApO1xuICAgIG5ld0J1ZmZlci5zZXQoZGF0YSwgYnVmZmVyLmxlbmd0aCk7XG4gICAgYnVmZmVyID0gbmV3QnVmZmVyO1xuICB9XG5cbiAgYXN5bmMgZnVuY3Rpb24gcHJvY2Vzc0ZyYW1lcyhcbiAgICBjb250cm9sbGVyOiBUcmFuc2Zvcm1TdHJlYW1EZWZhdWx0Q29udHJvbGxlcjxhbnk+XG4gICkge1xuICAgIC8vIFJlc29sdmUgdGhlIGtleSBwcm9taXNlIG9uY2Ugb24gZmlyc3QgdXNlIGFuZCBjYWNoZSB0aGUgcmVzdWx0XG4gICAgaWYgKCFrZXlTdGF0ZS5yZXNvbHZlZCkge1xuICAgICAga2V5U3RhdGUua2V5ID0gYXdhaXQgY3J5cHRvS2V5O1xuICAgICAga2V5U3RhdGUucmVzb2x2ZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIC8vIFRyeSB0byBleHRyYWN0IGNvbXBsZXRlIGxlbmd0aC1wcmVmaXhlZCBmcmFtZXNcbiAgICB3aGlsZSAoYnVmZmVyLmxlbmd0aCA+PSBGUkFNRV9IRUFERVJfU0laRSkge1xuICAgICAgY29uc3QgZnJhbWVMZW5ndGggPSBuZXcgRGF0YVZpZXcoXG4gICAgICAgIGJ1ZmZlci5idWZmZXIsXG4gICAgICAgIGJ1ZmZlci5ieXRlT2Zmc2V0LFxuICAgICAgICBidWZmZXIuYnl0ZUxlbmd0aFxuICAgICAgKS5nZXRVaW50MzIoMCwgZmFsc2UpO1xuXG4gICAgICBpZiAoYnVmZmVyLmxlbmd0aCA8IEZSQU1FX0hFQURFUl9TSVpFICsgZnJhbWVMZW5ndGgpIHtcbiAgICAgICAgYnJlYWs7IC8vIEluY29tcGxldGUgZnJhbWUsIHdhaXQgZm9yIG1vcmUgZGF0YVxuICAgICAgfVxuXG4gICAgICBjb25zdCBmcmFtZURhdGEgPSBidWZmZXIuc2xpY2UoXG4gICAgICAgIEZSQU1FX0hFQURFUl9TSVpFLFxuICAgICAgICBGUkFNRV9IRUFERVJfU0laRSArIGZyYW1lTGVuZ3RoXG4gICAgICApO1xuICAgICAgYnVmZmVyID0gYnVmZmVyLnNsaWNlKEZSQU1FX0hFQURFUl9TSVpFICsgZnJhbWVMZW5ndGgpO1xuXG4gICAgICBsZXQgeyBmb3JtYXQsIHBheWxvYWQgfSA9IGRlY29kZUZvcm1hdFByZWZpeChmcmFtZURhdGEpO1xuXG4gICAgICAvLyBJZiB0aGUgZnJhbWUgcGF5bG9hZCBpcyBlbmNyeXB0ZWQsIGRlY3J5cHQgaXQgZmlyc3QgdG8gcmV2ZWFsXG4gICAgICAvLyB0aGUgaW5uZXIgZm9ybWF0LXByZWZpeGVkIGRhdGEgKGUuZy4sICdkZXZsJyArIHNlcmlhbGl6ZWQgdGV4dCksXG4gICAgICAvLyB0aGVuIGZhbGwgdGhyb3VnaCB0byB0aGUgbm9ybWFsIGRlc2VyaWFsaXphdGlvbiBwYXRoLlxuICAgICAgaWYgKGZvcm1hdCA9PT0gU2VyaWFsaXphdGlvbkZvcm1hdC5FTkNSWVBURUQpIHtcbiAgICAgICAgaWYgKCFrZXlTdGF0ZS5rZXkpIHtcbiAgICAgICAgICBjb250cm9sbGVyLmVycm9yKFxuICAgICAgICAgICAgbmV3IFdvcmtmbG93UnVudGltZUVycm9yKFxuICAgICAgICAgICAgICAnRW5jcnlwdGVkIHN0cmVhbSBkYXRhIGVuY291bnRlcmVkIGJ1dCBubyBlbmNyeXB0aW9uIGtleSBpcyBhdmFpbGFibGUuICcgK1xuICAgICAgICAgICAgICAgICdFbmNyeXB0aW9uIGlzIG5vdCBjb25maWd1cmVkIG9yIG5vIGtleSB3YXMgcHJvdmlkZWQgZm9yIHRoaXMgcnVuLidcbiAgICAgICAgICAgIClcbiAgICAgICAgICApO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBkZWNyeXB0ZWQgPSBhd2FpdCBhZXNHY21EZWNyeXB0KGtleVN0YXRlLmtleSwgcGF5bG9hZCk7XG4gICAgICAgICh7IGZvcm1hdCwgcGF5bG9hZCB9ID0gZGVjb2RlRm9ybWF0UHJlZml4KGRlY3J5cHRlZCkpO1xuICAgICAgfVxuXG4gICAgICBpZiAoZm9ybWF0ID09PSBTZXJpYWxpemF0aW9uRm9ybWF0LkRFVkFMVUVfVjEpIHtcbiAgICAgICAgY29uc3QgdGV4dCA9IGRlY29kZXIuZGVjb2RlKHBheWxvYWQpO1xuICAgICAgICBjb250cm9sbGVyLmVucXVldWUocGFyc2UodGV4dCwgcmV2aXZlcnMpKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBjb25zdCBzdHJlYW0gPSBuZXcgVHJhbnNmb3JtU3RyZWFtPFVpbnQ4QXJyYXksIGFueT4oe1xuICAgIGFzeW5jIHRyYW5zZm9ybShjaHVuaywgY29udHJvbGxlcikge1xuICAgICAgLy8gRmlyc3QsIHRyeSB0byBkZXRlY3QgaWYgdGhpcyBpcyBsZW5ndGgtcHJlZml4ZWQgZnJhbWVkIGRhdGFcbiAgICAgIC8vIGJ5IGNoZWNraW5nIGlmIHRoZSBmaXJzdCA0IGJ5dGVzIGZvcm0gYSBwbGF1c2libGUgbGVuZ3RoLlxuICAgICAgaWYgKGJ1ZmZlci5sZW5ndGggPT09IDAgJiYgY2h1bmsubGVuZ3RoID49IEZSQU1FX0hFQURFUl9TSVpFKSB7XG4gICAgICAgIGNvbnN0IHBvc3NpYmxlTGVuZ3RoID0gbmV3IERhdGFWaWV3KFxuICAgICAgICAgIGNodW5rLmJ1ZmZlcixcbiAgICAgICAgICBjaHVuay5ieXRlT2Zmc2V0LFxuICAgICAgICAgIGNodW5rLmJ5dGVMZW5ndGhcbiAgICAgICAgKS5nZXRVaW50MzIoMCwgZmFsc2UpO1xuICAgICAgICBpZiAoXG4gICAgICAgICAgcG9zc2libGVMZW5ndGggPiAwICYmXG4gICAgICAgICAgcG9zc2libGVMZW5ndGggPCAxMDBfMDAwXzAwMCAvLyBzYW5pdHkgY2hlY2s6IDwgMTAwTUJcbiAgICAgICAgKSB7XG4gICAgICAgICAgLy8gTG9va3MgbGlrZSBmcmFtZWQgZGF0YVxuICAgICAgICAgIGFwcGVuZFRvQnVmZmVyKGNodW5rKTtcbiAgICAgICAgICBhd2FpdCBwcm9jZXNzRnJhbWVzKGNvbnRyb2xsZXIpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChidWZmZXIubGVuZ3RoID4gMCkge1xuICAgICAgICAvLyBBbHJlYWR5IGluIGZyYW1lZCBtb2RlIChoYXZlIGJ1ZmZlcmVkIGRhdGEpXG4gICAgICAgIGFwcGVuZFRvQnVmZmVyKGNodW5rKTtcbiAgICAgICAgYXdhaXQgcHJvY2Vzc0ZyYW1lcyhjb250cm9sbGVyKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICAvLyBMZWdhY3kgZm9ybWF0OiBuZXdsaW5lLWRlbGltaXRlZCBkZXZhbHVlIHRleHQgKG5vIGZyYW1pbmcpXG4gICAgICBjb25zdCB0ZXh0ID0gZGVjb2Rlci5kZWNvZGUoY2h1bmspO1xuICAgICAgY29uc3QgbGluZXMgPSB0ZXh0LnNwbGl0KCdcXG4nKTtcbiAgICAgIGZvciAoY29uc3QgbGluZSBvZiBsaW5lcykge1xuICAgICAgICBpZiAobGluZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgY29udHJvbGxlci5lbnF1ZXVlKHBhcnNlKGxpbmUsIHJldml2ZXJzKSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LFxuICAgIGFzeW5jIGZsdXNoKGNvbnRyb2xsZXIpIHtcbiAgICAgIC8vIFByb2Nlc3MgYW55IHJlbWFpbmluZyBmcmFtZWQgZGF0YVxuICAgICAgaWYgKGJ1ZmZlci5sZW5ndGggPiAwKSB7XG4gICAgICAgIGF3YWl0IHByb2Nlc3NGcmFtZXMoY29udHJvbGxlcik7XG4gICAgICB9XG4gICAgfSxcbiAgfSk7XG4gIHJldHVybiBzdHJlYW07XG59XG5cbmV4cG9ydCBjbGFzcyBXb3JrZmxvd1NlcnZlclJlYWRhYmxlU3RyZWFtIGV4dGVuZHMgUmVhZGFibGVTdHJlYW08VWludDhBcnJheT4ge1xuICAjcmVhZGVyPzogUmVhZGFibGVTdHJlYW1EZWZhdWx0UmVhZGVyPFVpbnQ4QXJyYXk+O1xuXG4gIGNvbnN0cnVjdG9yKHJ1bklkOiBzdHJpbmcsIG5hbWU6IHN0cmluZywgc3RhcnRJbmRleD86IG51bWJlcikge1xuICAgIGlmICh0eXBlb2YgbmFtZSAhPT0gJ3N0cmluZycgfHwgbmFtZS5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgXCJuYW1lXCIgaXMgcmVxdWlyZWQsIGdvdCBcIiR7bmFtZX1cImApO1xuICAgIH1cbiAgICBzdXBlcih7XG4gICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIE5vdCBzdXJlIHdoeSBUeXBlU2NyaXB0IGlzIGNvbXBsYWluaW5nIGFib3V0IHRoaXNcbiAgICAgIHR5cGU6ICdieXRlcycsXG5cbiAgICAgIHB1bGw6IGFzeW5jIChjb250cm9sbGVyKSA9PiB7XG4gICAgICAgIGxldCByZWFkZXIgPSB0aGlzLiNyZWFkZXI7XG4gICAgICAgIGlmICghcmVhZGVyKSB7XG4gICAgICAgICAgY29uc3Qgd29ybGQgPSBhd2FpdCBnZXRXb3JsZCgpO1xuICAgICAgICAgIGNvbnN0IHN0cmVhbSA9IGF3YWl0IHdvcmxkLnN0cmVhbXMuZ2V0KHJ1bklkLCBuYW1lLCBzdGFydEluZGV4KTtcbiAgICAgICAgICByZWFkZXIgPSB0aGlzLiNyZWFkZXIgPSBzdHJlYW0uZ2V0UmVhZGVyKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFyZWFkZXIpIHtcbiAgICAgICAgICBjb250cm9sbGVyLmVycm9yKG5ldyBFcnJvcignRmFpbGVkIHRvIGdldCByZWFkZXInKSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcmVhZGVyLnJlYWQoKTtcbiAgICAgICAgaWYgKHJlc3VsdC5kb25lKSB7XG4gICAgICAgICAgdGhpcy4jcmVhZGVyID0gdW5kZWZpbmVkO1xuICAgICAgICAgIGNvbnRyb2xsZXIuY2xvc2UoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBGb3J3YXJkIHJhdyBieXRlczsgZW5jcnlwdGlvbi9kZWNyeXB0aW9uIGlzIGhhbmRsZWQgYXQgdGhlXG4gICAgICAgICAgLy8gZnJhbWluZyBsZXZlbCBieSBnZXRTZXJpYWxpemVTdHJlYW0vZ2V0RGVzZXJpYWxpemVTdHJlYW0uXG4gICAgICAgICAgY29udHJvbGxlci5lbnF1ZXVlKHJlc3VsdC52YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBjYW5jZWw6IGFzeW5jIChyZWFzb24pID0+IHtcbiAgICAgICAgaWYgKHRoaXMuI3JlYWRlcikge1xuICAgICAgICAgIGF3YWl0IHRoaXMuI3JlYWRlci5jYW5jZWwocmVhc29uKS5jYXRjaCgoKSA9PiB7fSk7XG4gICAgICAgICAgdGhpcy4jcmVhZGVyID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgIH0pO1xuICB9XG59XG5cbi8qKlxuICogRGVmYXVsdCBmbHVzaCBpbnRlcnZhbCBpbiBtaWxsaXNlY29uZHMgZm9yIGJ1ZmZlcmVkIHN0cmVhbSB3cml0ZXMuXG4gKiBDaHVua3MgYXJlIGFjY3VtdWxhdGVkIGFuZCBmbHVzaGVkIHRvZ2V0aGVyIHRvIHJlZHVjZSBuZXR3b3JrIG92ZXJoZWFkLlxuICovXG5jb25zdCBTVFJFQU1fRkxVU0hfSU5URVJWQUxfTVMgPSAxMDtcblxuZXhwb3J0IGNsYXNzIFdvcmtmbG93U2VydmVyV3JpdGFibGVTdHJlYW0gZXh0ZW5kcyBXcml0YWJsZVN0cmVhbTxVaW50OEFycmF5PiB7XG4gIGNvbnN0cnVjdG9yKHJ1bklkOiBzdHJpbmcsIG5hbWU6IHN0cmluZykge1xuICAgIGlmICh0eXBlb2YgcnVuSWQgIT09ICdzdHJpbmcnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFwicnVuSWRcIiBtdXN0IGJlIGEgc3RyaW5nLCBnb3QgXCIke3R5cGVvZiBydW5JZH1cImApO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIG5hbWUgIT09ICdzdHJpbmcnIHx8IG5hbWUubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFwibmFtZVwiIGlzIHJlcXVpcmVkLCBnb3QgXCIke25hbWV9XCJgKTtcbiAgICB9XG4gICAgY29uc3Qgd29ybGRQcm9taXNlID0gZ2V0V29ybGQoKTtcblxuICAgIC8vIEJ1ZmZlcmluZyBzdGF0ZSBmb3IgYmF0Y2hlZCB3cml0ZXNcbiAgICAvLyBFbmNyeXB0aW9uL2RlY3J5cHRpb24gaXMgaGFuZGxlZCBhdCB0aGUgZnJhbWluZyBsZXZlbCBieVxuICAgIC8vIGdldFNlcmlhbGl6ZVN0cmVhbS9nZXREZXNlcmlhbGl6ZVN0cmVhbSwgbm90IGhlcmUuXG4gICAgbGV0IGJ1ZmZlcjogVWludDhBcnJheVtdID0gW107XG4gICAgbGV0IGZsdXNoVGltZXI6IFJldHVyblR5cGU8dHlwZW9mIHNldFRpbWVvdXQ+IHwgbnVsbCA9IG51bGw7XG4gICAgbGV0IGZsdXNoUHJvbWlzZTogUHJvbWlzZTx2b2lkPiB8IG51bGwgPSBudWxsO1xuICAgIGxldCByZXNvbHZlZEZsdXNoSW50ZXJ2YWxNczogbnVtYmVyIHwgdW5kZWZpbmVkO1xuXG4gICAgY29uc3QgZmx1c2ggPSBhc3luYyAoKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICBpZiAoZmx1c2hUaW1lcikge1xuICAgICAgICBjbGVhclRpbWVvdXQoZmx1c2hUaW1lcik7XG4gICAgICAgIGZsdXNoVGltZXIgPSBudWxsO1xuICAgICAgfVxuXG4gICAgICBpZiAoYnVmZmVyLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xuXG4gICAgICAvLyBDb3B5IGNodW5rcyB0byBmbHVzaCwgYnV0IGRvbid0IGNsZWFyIGJ1ZmZlciB1bnRpbCB3cml0ZSBzdWNjZWVkc1xuICAgICAgLy8gVGhpcyBwcmV2ZW50cyBkYXRhIGxvc3MgaWYgdGhlIHdyaXRlIG9wZXJhdGlvbiBmYWlsc1xuICAgICAgY29uc3QgY2h1bmtzVG9GbHVzaCA9IGJ1ZmZlci5zbGljZSgpO1xuXG4gICAgICBjb25zdCB3b3JsZCA9IGF3YWl0IHdvcmxkUHJvbWlzZTtcbiAgICAgIC8vIENhY2hlIHRoZSBmbHVzaCBpbnRlcnZhbCBmcm9tIHRoZSB3b3JsZCBvbiBmaXJzdCB1c2VcbiAgICAgIGlmIChyZXNvbHZlZEZsdXNoSW50ZXJ2YWxNcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJlc29sdmVkRmx1c2hJbnRlcnZhbE1zID1cbiAgICAgICAgICB3b3JsZC5zdHJlYW1GbHVzaEludGVydmFsTXMgPz8gU1RSRUFNX0ZMVVNIX0lOVEVSVkFMX01TO1xuICAgICAgfVxuICAgICAgLy8gVXNlIHdyaXRlTXVsdGkgaWYgYXZhaWxhYmxlIGZvciBiYXRjaCB3cml0ZXNcbiAgICAgIGlmIChcbiAgICAgICAgdHlwZW9mIHdvcmxkLnN0cmVhbXMud3JpdGVNdWx0aSA9PT0gJ2Z1bmN0aW9uJyAmJlxuICAgICAgICBjaHVua3NUb0ZsdXNoLmxlbmd0aCA+IDFcbiAgICAgICkge1xuICAgICAgICBhd2FpdCB3b3JsZC5zdHJlYW1zLndyaXRlTXVsdGkocnVuSWQsIG5hbWUsIGNodW5rc1RvRmx1c2gpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gRmFsbCBiYWNrIHRvIHNlcXVlbnRpYWwgd3JpdGVzXG4gICAgICAgIGZvciAoY29uc3QgY2h1bmsgb2YgY2h1bmtzVG9GbHVzaCkge1xuICAgICAgICAgIGF3YWl0IHdvcmxkLnN0cmVhbXMud3JpdGUocnVuSWQsIG5hbWUsIGNodW5rKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBPbmx5IGNsZWFyIGJ1ZmZlciBhZnRlciBzdWNjZXNzZnVsIHdyaXRlIHRvIHByZXZlbnQgZGF0YSBsb3NzXG4gICAgICBidWZmZXIgPSBbXTtcbiAgICB9O1xuXG4gICAgLyoqIFJlc29sdmVycy9yZWplY3RvcnMgd2FpdGluZyBmb3IgdGhlIGN1cnJlbnQgc2NoZWR1bGVkIGZsdXNoICovXG4gICAgbGV0IGZsdXNoV2FpdGVyczogQXJyYXk8e1xuICAgICAgcmVzb2x2ZTogKCkgPT4gdm9pZDtcbiAgICAgIHJlamVjdDogKGVycjogdW5rbm93bikgPT4gdm9pZDtcbiAgICB9PiA9IFtdO1xuXG4gICAgY29uc3Qgc2NoZWR1bGVGbHVzaCA9ICgpOiB2b2lkID0+IHtcbiAgICAgIGlmIChmbHVzaFRpbWVyKSByZXR1cm47IC8vIEFscmVhZHkgc2NoZWR1bGVkXG5cbiAgICAgIGZsdXNoVGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgZmx1c2hUaW1lciA9IG51bGw7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRXYWl0ZXJzID0gZmx1c2hXYWl0ZXJzO1xuICAgICAgICBmbHVzaFdhaXRlcnMgPSBbXTtcbiAgICAgICAgZmx1c2hQcm9taXNlID0gZmx1c2goKS50aGVuKFxuICAgICAgICAgICgpID0+IHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgdyBvZiBjdXJyZW50V2FpdGVycykgdy5yZXNvbHZlKCk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICAoZXJyKSA9PiB7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHcgb2YgY3VycmVudFdhaXRlcnMpIHcucmVqZWN0KGVycik7XG4gICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgfSwgcmVzb2x2ZWRGbHVzaEludGVydmFsTXMgPz8gU1RSRUFNX0ZMVVNIX0lOVEVSVkFMX01TKTtcbiAgICB9O1xuXG4gICAgc3VwZXIoe1xuICAgICAgYXN5bmMgd3JpdGUoY2h1bmspIHtcbiAgICAgICAgLy8gV2FpdCBmb3IgYW55IGluLXByb2dyZXNzIGZsdXNoIHRvIGNvbXBsZXRlIGJlZm9yZSBhZGRpbmcgdG8gYnVmZmVyXG4gICAgICAgIGlmIChmbHVzaFByb21pc2UpIHtcbiAgICAgICAgICBhd2FpdCBmbHVzaFByb21pc2U7XG4gICAgICAgICAgZmx1c2hQcm9taXNlID0gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGJ1ZmZlci5wdXNoKGNodW5rKTtcbiAgICAgICAgc2NoZWR1bGVGbHVzaCgpO1xuXG4gICAgICAgIC8vIFdhaXQgZm9yIHRoZSBzY2hlZHVsZWQgZmx1c2ggdG8gY29tcGxldGUgc28gdGhhdCBjYWxsZXJzXG4gICAgICAgIC8vIChsaWtlIGZsdXNoYWJsZVBpcGUpIGtub3cgZGF0YSBoYXMgcmVhY2hlZCB0aGUgc2VydmVyXG4gICAgICAgIC8vIGJlZm9yZSBkZWNyZW1lbnRpbmcgcGVuZGluZ09wcy4gV2l0aG91dCB0aGlzLCBwZW5kaW5nT3BzXG4gICAgICAgIC8vIHJlYWNoZXMgMCB3aGVuIHRoZSBidWZmZXJlZCB3cml0ZSByZXR1cm5zIChpbnN0YW50KSwgYnV0XG4gICAgICAgIC8vIHRoZSAxMG1zIGZsdXNoIHRpbWVyIGhhc24ndCBmaXJlZCB5ZXQuXG4gICAgICAgIGF3YWl0IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICBmbHVzaFdhaXRlcnMucHVzaCh7IHJlc29sdmUsIHJlamVjdCB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9LFxuICAgICAgYXN5bmMgY2xvc2UoKSB7XG4gICAgICAgIC8vIFdhaXQgZm9yIGFueSBpbi1wcm9ncmVzcyBmbHVzaCB0byBjb21wbGV0ZVxuICAgICAgICBpZiAoZmx1c2hQcm9taXNlKSB7XG4gICAgICAgICAgYXdhaXQgZmx1c2hQcm9taXNlO1xuICAgICAgICAgIGZsdXNoUHJvbWlzZSA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBGbHVzaCBhbnkgcmVtYWluaW5nIGJ1ZmZlcmVkIGNodW5rc1xuICAgICAgICBhd2FpdCBmbHVzaCgpO1xuXG4gICAgICAgIGNvbnN0IHdvcmxkID0gYXdhaXQgd29ybGRQcm9taXNlO1xuICAgICAgICBhd2FpdCB3b3JsZC5zdHJlYW1zLmNsb3NlKHJ1bklkLCBuYW1lKTtcbiAgICAgIH0sXG4gICAgICBhYm9ydChyZWFzb24pIHtcbiAgICAgICAgLy8gQ2xlYW4gdXAgdGltZXIgdG8gcHJldmVudCBsZWFrc1xuICAgICAgICBpZiAoZmx1c2hUaW1lcikge1xuICAgICAgICAgIGNsZWFyVGltZW91dChmbHVzaFRpbWVyKTtcbiAgICAgICAgICBmbHVzaFRpbWVyID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICAvLyBEaXNjYXJkIGJ1ZmZlcmVkIGNodW5rcyAtIHRoZXkgd29uJ3QgYmUgd3JpdHRlblxuICAgICAgICBidWZmZXIgPSBbXTtcbiAgICAgICAgLy8gUmVqZWN0IGFueSBwZW5kaW5nIGZsdXNoV2FpdGVycyBzbyB0aGUgd3JpdGUoKSBwcm9taXNlcyBzZXR0bGVcbiAgICAgICAgLy8gYW5kIGRvbid0IGxlYWsuIFdpdGhvdXQgdGhpcywgd3JpdGUoKSBoYW5ncyBmb3JldmVyIG9uIGFuXG4gICAgICAgIC8vIHVuc2V0dGxlZCBwcm9taXNlIGJlY2F1c2UgdGhlIGNsZWFyZWQgdGltZXIgd2lsbCBuZXZlciBmaXJlLlxuICAgICAgICBjb25zdCB3YWl0ZXJzID0gZmx1c2hXYWl0ZXJzO1xuICAgICAgICBmbHVzaFdhaXRlcnMgPSBbXTtcbiAgICAgICAgY29uc3QgYWJvcnRFcnJvciA9IHJlYXNvbiA/PyBuZXcgRXJyb3IoJ1N0cmVhbSBhYm9ydGVkJyk7XG4gICAgICAgIGZvciAoY29uc3QgdyBvZiB3YWl0ZXJzKSB3LnJlamVjdChhYm9ydEVycm9yKTtcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cbn1cblxuLy8gVHlwZXMgdGhhdCBuZWVkIHNwZWNpYWxpemVkIGhhbmRsaW5nIHdoZW4gc2VyaWFsaXplZC9kZXNlcmlhbGl6ZWRcbi8vICEgSWYgYSB0eXBlIGlzIGFkZGVkIGhlcmUsIGl0IE1VU1QgYWxzbyBiZSBhZGRlZCB0byB0aGUgYFNlcmlhbGl6YWJsZWAgdHlwZSBpbiBgc2NoZW1hcy50c2BcbmV4cG9ydCBpbnRlcmZhY2UgU2VyaWFsaXphYmxlU3BlY2lhbCB7XG4gIEFycmF5QnVmZmVyOiBzdHJpbmc7IC8vIGJhc2U2NCBzdHJpbmdcbiAgQmlnSW50OiBzdHJpbmc7IC8vIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBiaWdpbnRcbiAgQmlnSW50NjRBcnJheTogc3RyaW5nOyAvLyBiYXNlNjQgc3RyaW5nXG4gIEJpZ1VpbnQ2NEFycmF5OiBzdHJpbmc7IC8vIGJhc2U2NCBzdHJpbmdcbiAgRGF0ZTogc3RyaW5nOyAvLyBJU08gc3RyaW5nXG4gIERPTUV4Y2VwdGlvbjoge1xuICAgIG1lc3NhZ2U6IHN0cmluZztcbiAgICBuYW1lOiBzdHJpbmc7XG4gICAgc3RhY2s/OiBzdHJpbmc7XG4gICAgY2F1c2U/OiB1bmtub3duO1xuICB9O1xuICBGbG9hdDMyQXJyYXk6IHN0cmluZzsgLy8gYmFzZTY0IHN0cmluZ1xuICBGbG9hdDY0QXJyYXk6IHN0cmluZzsgLy8gYmFzZTY0IHN0cmluZ1xuICBFcnJvcjogUmVjb3JkPHN0cmluZywgYW55PjtcbiAgSGVhZGVyczogW3N0cmluZywgc3RyaW5nXVtdO1xuICBJbnQ4QXJyYXk6IHN0cmluZzsgLy8gYmFzZTY0IHN0cmluZ1xuICBJbnQxNkFycmF5OiBzdHJpbmc7IC8vIGJhc2U2NCBzdHJpbmdcbiAgSW50MzJBcnJheTogc3RyaW5nOyAvLyBiYXNlNjQgc3RyaW5nXG4gIE1hcDogW2FueSwgYW55XVtdO1xuICBSZWFkYWJsZVN0cmVhbTpcbiAgICB8IHsgbmFtZTogc3RyaW5nOyB0eXBlPzogJ2J5dGVzJzsgc3RhcnRJbmRleD86IG51bWJlciB9XG4gICAgfCB7IGJvZHlJbml0OiBhbnkgfTtcbiAgUmVnRXhwOiB7IHNvdXJjZTogc3RyaW5nOyBmbGFnczogc3RyaW5nIH07XG4gIFJlcXVlc3Q6IHtcbiAgICBtZXRob2Q6IHN0cmluZztcbiAgICB1cmw6IHN0cmluZztcbiAgICBoZWFkZXJzOiBIZWFkZXJzO1xuICAgIGJvZHk6IFJlcXVlc3RbJ2JvZHknXTtcbiAgICBkdXBsZXg6IFJlcXVlc3RbJ2R1cGxleCddO1xuXG4gICAgLy8gVGhpcyBpcyBzcGVjaWZpY2FsbHkgZm9yIHRoZSBgUmVxdWVzdFdpdGhSZXNwb25zZWAgdHlwZSB3aGljaCBpcyB1c2VkIGZvciB3ZWJob29rc1xuICAgIHJlc3BvbnNlV3JpdGFibGU/OiBXcml0YWJsZVN0cmVhbTxSZXNwb25zZT47XG4gIH07XG4gIFJlc3BvbnNlOiB7XG4gICAgdHlwZTogUmVzcG9uc2VbJ3R5cGUnXTtcbiAgICB1cmw6IHN0cmluZztcbiAgICBzdGF0dXM6IG51bWJlcjtcbiAgICBzdGF0dXNUZXh0OiBzdHJpbmc7XG4gICAgaGVhZGVyczogSGVhZGVycztcbiAgICBib2R5OiBSZXNwb25zZVsnYm9keSddO1xuICAgIHJlZGlyZWN0ZWQ6IGJvb2xlYW47XG4gIH07XG4gIENsYXNzOiB7XG4gICAgY2xhc3NJZDogc3RyaW5nO1xuICB9O1xuICAvKipcbiAgICogQ3VzdG9tIHNlcmlhbGl6ZWQgY2xhc3MgaW5zdGFuY2UuXG4gICAqIFRoZSBjbGFzcyBtdXN0IGhhdmUgYSBgY2xhc3NJZGAgcHJvcGVydHkgYW5kIGJlIHJlZ2lzdGVyZWQgZm9yIGRlc2VyaWFsaXphdGlvbi5cbiAgICovXG4gIEluc3RhbmNlOiB7XG4gICAgY2xhc3NJZDogc3RyaW5nOyAvLyBVbmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIGNsYXNzICh1c2VkIGZvciBsb29rdXAgZHVyaW5nIGRlc2VyaWFsaXphdGlvbilcbiAgICBkYXRhOiB1bmtub3duOyAvLyBUaGUgc2VyaWFsaXplZCBpbnN0YW5jZSBkYXRhXG4gIH07XG4gIFNldDogYW55W107XG4gIFN0ZXBGdW5jdGlvbjoge1xuICAgIHN0ZXBJZDogc3RyaW5nO1xuICAgIGNsb3N1cmVWYXJzPzogUmVjb3JkPHN0cmluZywgYW55PjtcbiAgfTtcbiAgVVJMOiBzdHJpbmc7XG4gIFdvcmtmbG93RnVuY3Rpb246IHtcbiAgICB3b3JrZmxvd0lkOiBzdHJpbmc7XG4gIH07XG4gIFVSTFNlYXJjaFBhcmFtczogc3RyaW5nO1xuICBVaW50OEFycmF5OiBzdHJpbmc7IC8vIGJhc2U2NCBzdHJpbmdcbiAgVWludDhDbGFtcGVkQXJyYXk6IHN0cmluZzsgLy8gYmFzZTY0IHN0cmluZ1xuICBVaW50MTZBcnJheTogc3RyaW5nOyAvLyBiYXNlNjQgc3RyaW5nXG4gIFVpbnQzMkFycmF5OiBzdHJpbmc7IC8vIGJhc2U2NCBzdHJpbmdcbiAgV3JpdGFibGVTdHJlYW06IHsgbmFtZTogc3RyaW5nIH07XG59XG5cbnR5cGUgUmVkdWNlcnMgPSB7XG4gIFtLIGluIGtleW9mIFNlcmlhbGl6YWJsZVNwZWNpYWxdOiAoXG4gICAgdmFsdWU6IGFueVxuICApID0+IFNlcmlhbGl6YWJsZVNwZWNpYWxbS10gfCBmYWxzZTtcbn07XG5cbnR5cGUgUmV2aXZlcnMgPSB7XG4gIFtLIGluIGtleW9mIFNlcmlhbGl6YWJsZVNwZWNpYWxdOiAodmFsdWU6IFNlcmlhbGl6YWJsZVNwZWNpYWxbS10pID0+IGFueTtcbn07XG5cbmZ1bmN0aW9uIHJldml2ZShzdHI6IHN0cmluZykge1xuICAvLyBiaW9tZS1pZ25vcmUgbGludC9zZWN1cml0eS9ub0dsb2JhbEV2YWw6IEV2YWwgaXMgc2FmZSBoZXJlIC0gd2UgYXJlIG9ubHkgcGFzc2luZyB2YWx1ZSBmcm9tIGBkZXZhbHVlLnN0cmluZ2lmeSgpYFxuICAvLyBiaW9tZS1pZ25vcmUgbGludC9jb21wbGV4aXR5L25vQ29tbWFPcGVyYXRvcjogVGhpcyBpcyBob3cgeW91IGRvIGdsb2JhbCBzY29wZSBldmFsXG4gIHJldHVybiAoMCwgZXZhbCkoYCgke3N0cn0pYCk7XG59XG5cbmZ1bmN0aW9uIGdldENvbW1vblJlZHVjZXJzKGdsb2JhbDogUmVjb3JkPHN0cmluZywgYW55PiA9IGdsb2JhbFRoaXMpIHtcbiAgY29uc3QgYWJUb0Jhc2U2NCA9IChcbiAgICB2YWx1ZTogQXJyYXlCdWZmZXJMaWtlLFxuICAgIG9mZnNldDogbnVtYmVyLFxuICAgIGxlbmd0aDogbnVtYmVyXG4gICkgPT4ge1xuICAgIC8vIEF2b2lkIHJldHVybmluZyBmYWxzeSB2YWx1ZSBmb3IgemVyby1sZW5ndGggYnVmZmVyc1xuICAgIGlmIChsZW5ndGggPT09IDApIHJldHVybiAnLic7XG4gICAgLy8gQ3JlYXRlIGEgcHJvcGVyIGNvcHkgdG8gYXZvaWQgQXJyYXlCdWZmZXIgZGV0YWNobWVudCBpc3N1ZXNcbiAgICAvLyBCdWZmZXIuZnJvbShBcnJheUJ1ZmZlciwgb2Zmc2V0LCBsZW5ndGgpIGNyZWF0ZXMgYSB2aWV3LCBub3QgYSBjb3B5XG4gICAgY29uc3QgdWludDggPSBuZXcgVWludDhBcnJheSh2YWx1ZSwgb2Zmc2V0LCBsZW5ndGgpO1xuICAgIHJldHVybiBCdWZmZXIuZnJvbSh1aW50OCkudG9TdHJpbmcoJ2Jhc2U2NCcpO1xuICB9O1xuICBjb25zdCB2aWV3VG9CYXNlNjQgPSAodmFsdWU6IEFycmF5QnVmZmVyVmlldykgPT5cbiAgICBhYlRvQmFzZTY0KHZhbHVlLmJ1ZmZlciwgdmFsdWUuYnl0ZU9mZnNldCwgdmFsdWUuYnl0ZUxlbmd0aCk7XG5cbiAgcmV0dXJuIHtcbiAgICBBcnJheUJ1ZmZlcjogKHZhbHVlKSA9PlxuICAgICAgdmFsdWUgaW5zdGFuY2VvZiBnbG9iYWwuQXJyYXlCdWZmZXIgJiZcbiAgICAgIGFiVG9CYXNlNjQodmFsdWUsIDAsIHZhbHVlLmJ5dGVMZW5ndGgpLFxuICAgIEJpZ0ludDogKHZhbHVlKSA9PiB0eXBlb2YgdmFsdWUgPT09ICdiaWdpbnQnICYmIHZhbHVlLnRvU3RyaW5nKCksXG4gICAgQmlnSW50NjRBcnJheTogKHZhbHVlKSA9PlxuICAgICAgdmFsdWUgaW5zdGFuY2VvZiBnbG9iYWwuQmlnSW50NjRBcnJheSAmJiB2aWV3VG9CYXNlNjQodmFsdWUpLFxuICAgIEJpZ1VpbnQ2NEFycmF5OiAodmFsdWUpID0+XG4gICAgICB2YWx1ZSBpbnN0YW5jZW9mIGdsb2JhbC5CaWdVaW50NjRBcnJheSAmJiB2aWV3VG9CYXNlNjQodmFsdWUpLFxuICAgIC8vIENsYXNzIGFuZCBJbnN0YW5jZSBhcmUgaW50ZW50aW9uYWxseSBwbGFjZWQgYmVmb3JlIEVycm9yIHNvIHRoYXRcbiAgICAvLyBjdXN0b20gRXJyb3Igc3ViY2xhc3NlcyB3aXRoIFdPUktGTE9XX1NFUklBTElaRSB0YWtlIHByZWNlZGVuY2VcbiAgICAvLyBvdmVyIHRoZSBnZW5lcmljIEVycm9yIHNlcmlhbGl6YXRpb24gKGRldmFsdWUgdXNlcyBmaXJzdC1tYXRjaC13aW5zKS5cbiAgICBDbGFzczogKHZhbHVlKSA9PiB7XG4gICAgICAvLyBDaGVjayBpZiB0aGlzIGlzIGEgY2xhc3MgY29uc3RydWN0b3Igd2l0aCBhIGNsYXNzSWQgcHJvcGVydHlcbiAgICAgIC8vIChzZXQgYnkgdGhlIFNXQyBwbHVnaW4gZm9yIGNsYXNzZXMgd2l0aCBzdGF0aWMgc3RlcC93b3JrZmxvdyBtZXRob2RzKVxuICAgICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ2Z1bmN0aW9uJykgcmV0dXJuIGZhbHNlO1xuICAgICAgY29uc3QgY2xhc3NJZCA9ICh2YWx1ZSBhcyBhbnkpLmNsYXNzSWQ7XG4gICAgICBpZiAodHlwZW9mIGNsYXNzSWQgIT09ICdzdHJpbmcnKSByZXR1cm4gZmFsc2U7XG4gICAgICByZXR1cm4geyBjbGFzc0lkIH07XG4gICAgfSxcbiAgICBJbnN0YW5jZTogKHZhbHVlKSA9PiB7XG4gICAgICAvLyBDaGVjayBpZiB0aGlzIGlzIGFuIGluc3RhbmNlIG9mIGEgY2xhc3Mgd2l0aCBjdXN0b20gc2VyaWFsaXphdGlvblxuICAgICAgaWYgKHZhbHVlID09PSBudWxsIHx8IHR5cGVvZiB2YWx1ZSAhPT0gJ29iamVjdCcpIHJldHVybiBmYWxzZTtcbiAgICAgIGNvbnN0IGNscyA9IHZhbHVlLmNvbnN0cnVjdG9yO1xuICAgICAgaWYgKCFjbHMgfHwgdHlwZW9mIGNscyAhPT0gJ2Z1bmN0aW9uJykgcmV0dXJuIGZhbHNlO1xuXG4gICAgICAvLyBDaGVjayBpZiB0aGUgY2xhc3MgaGFzIGEgc3RhdGljIFdPUktGTE9XX1NFUklBTElaRSBtZXRob2RcbiAgICAgIGNvbnN0IHNlcmlhbGl6ZSA9IGNsc1tXT1JLRkxPV19TRVJJQUxJWkVdO1xuICAgICAgaWYgKHR5cGVvZiBzZXJpYWxpemUgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuXG4gICAgICAvLyBHZXQgdGhlIGNsYXNzSWQgZnJvbSB0aGUgc3RhdGljIGNsYXNzIHByb3BlcnR5IChzZXQgYnkgU1dDIHBsdWdpbilcbiAgICAgIGNvbnN0IGNsYXNzSWQgPSBjbHMuY2xhc3NJZDtcbiAgICAgIGlmICh0eXBlb2YgY2xhc3NJZCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBDbGFzcyBcIiR7Y2xzLm5hbWV9XCIgd2l0aCAke1N0cmluZyhXT1JLRkxPV19TRVJJQUxJWkUpfSBtdXN0IGhhdmUgYSBzdGF0aWMgXCJjbGFzc0lkXCIgcHJvcGVydHkuYFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICAvLyBTZXJpYWxpemUgdGhlIGluc3RhbmNlIHVzaW5nIHRoZSBjdXN0b20gc2VyaWFsaXplclxuICAgICAgY29uc3QgZGF0YSA9IHNlcmlhbGl6ZS5jYWxsKGNscywgdmFsdWUpO1xuICAgICAgcmV0dXJuIHsgY2xhc3NJZCwgZGF0YSB9O1xuICAgIH0sXG4gICAgRGF0ZTogKHZhbHVlKSA9PiB7XG4gICAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIGdsb2JhbC5EYXRlKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgY29uc3QgdmFsaWQgPSAhTnVtYmVyLmlzTmFOKHZhbHVlLmdldERhdGUoKSk7XG4gICAgICAvLyBOb3RlOiBcIi5cIiBpcyB0byBhdm9pZCByZXR1cm5pbmcgYSBmYWxzeSB2YWx1ZSB3aGVuIHRoZSBkYXRlIGlzIGludmFsaWRcbiAgICAgIHJldHVybiB2YWxpZCA/IHZhbHVlLnRvSVNPU3RyaW5nKCkgOiAnLic7XG4gICAgfSxcbiAgICAvLyBET01FeGNlcHRpb24gaXMgYSBzcGVjaWFsIGNhc2U6IGluIE5vZGUuanMgaXQgcGFzc2VzIGlzTmF0aXZlRXJyb3IoKVxuICAgIC8vIGFuZCBpbnN0YW5jZW9mIEVycm9yLCBidXQgaGFzIGEgdW5pcXVlIGNvbnN0cnVjdG9yIHNpZ25hdHVyZVxuICAgIC8vIChtZXNzYWdlLCBuYW1lKSBhbmQgYSByZWFkLW9ubHkgbnVtZXJpYyBgY29kZWAgcHJvcGVydHkgZGVyaXZlZCBmcm9tXG4gICAgLy8gYG5hbWVgLiBJdCBtdXN0IGJlIGNoZWNrZWQgYmVmb3JlIHRoZSBnZW5lcmljIEVycm9yIHJlZHVjZXIuXG4gICAgRE9NRXhjZXB0aW9uOiAodmFsdWUpID0+IHtcbiAgICAgIGlmICghdHlwZXMuaXNOYXRpdmVFcnJvcih2YWx1ZSkpIHJldHVybiBmYWxzZTtcbiAgICAgIGlmICh2YWx1ZS5jb25zdHJ1Y3Rvcj8ubmFtZSAhPT0gJ0RPTUV4Y2VwdGlvbicpIHJldHVybiBmYWxzZTtcbiAgICAgIGNvbnN0IHJlZHVjZWQ6IFNlcmlhbGl6YWJsZVNwZWNpYWxbJ0RPTUV4Y2VwdGlvbiddID0ge1xuICAgICAgICBtZXNzYWdlOiB2YWx1ZS5tZXNzYWdlLFxuICAgICAgICBuYW1lOiB2YWx1ZS5uYW1lLFxuICAgICAgICBzdGFjazogdmFsdWUuc3RhY2ssXG4gICAgICB9O1xuICAgICAgaWYgKCdjYXVzZScgaW4gdmFsdWUpIHJlZHVjZWQuY2F1c2UgPSB2YWx1ZS5jYXVzZTtcbiAgICAgIHJldHVybiByZWR1Y2VkO1xuICAgIH0sXG4gICAgRXJyb3I6ICh2YWx1ZSkgPT4ge1xuICAgICAgLy8gVXNlIHR5cGVzLmlzTmF0aXZlRXJyb3IoKSBpbnN0ZWFkIG9mIGBpbnN0YW5jZW9mIGdsb2JhbC5FcnJvcmBcbiAgICAgIC8vIGJlY2F1c2UgZXJyb3JzIG1heSBvcmlnaW5hdGUgZnJvbSBhIGRpZmZlcmVudCBWTSBjb250ZXh0IChlLmcuXG4gICAgICAvLyBGYXRhbEVycm9yIGZyb20gdGhlIGhvc3QgY29udGV4dCBwYXNzZWQgaW50byBhIFZNLWNvbnRleHQgd29ya2Zsb3cpLlxuICAgICAgLy8gYGluc3RhbmNlb2ZgIGNoZWNrcyBmYWlsIGFjcm9zcyBWTSBib3VuZGFyaWVzIHNpbmNlIGVhY2ggY29udGV4dFxuICAgICAgLy8gaGFzIGl0cyBvd24gRXJyb3IgY29uc3RydWN0b3IsIGJ1dCBpc05hdGl2ZUVycm9yKCkgdXNlcyBWOCdzXG4gICAgICAvLyBpbnRlcm5hbCB0eXBlIHRhZyB3aGljaCB3b3JrcyBhY3Jvc3MgYWxsIGNvbnRleHRzLlxuICAgICAgaWYgKCF0eXBlcy5pc05hdGl2ZUVycm9yKHZhbHVlKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgbmFtZTogdmFsdWUubmFtZSxcbiAgICAgICAgbWVzc2FnZTogdmFsdWUubWVzc2FnZSxcbiAgICAgICAgc3RhY2s6IHZhbHVlLnN0YWNrLFxuICAgICAgfTtcbiAgICB9LFxuICAgIEZsb2F0MzJBcnJheTogKHZhbHVlKSA9PlxuICAgICAgdmFsdWUgaW5zdGFuY2VvZiBnbG9iYWwuRmxvYXQzMkFycmF5ICYmIHZpZXdUb0Jhc2U2NCh2YWx1ZSksXG4gICAgRmxvYXQ2NEFycmF5OiAodmFsdWUpID0+XG4gICAgICB2YWx1ZSBpbnN0YW5jZW9mIGdsb2JhbC5GbG9hdDY0QXJyYXkgJiYgdmlld1RvQmFzZTY0KHZhbHVlKSxcbiAgICBIZWFkZXJzOiAodmFsdWUpID0+IHZhbHVlIGluc3RhbmNlb2YgZ2xvYmFsLkhlYWRlcnMgJiYgQXJyYXkuZnJvbSh2YWx1ZSksXG4gICAgSW50OEFycmF5OiAodmFsdWUpID0+XG4gICAgICB2YWx1ZSBpbnN0YW5jZW9mIGdsb2JhbC5JbnQ4QXJyYXkgJiYgdmlld1RvQmFzZTY0KHZhbHVlKSxcbiAgICBJbnQxNkFycmF5OiAodmFsdWUpID0+XG4gICAgICB2YWx1ZSBpbnN0YW5jZW9mIGdsb2JhbC5JbnQxNkFycmF5ICYmIHZpZXdUb0Jhc2U2NCh2YWx1ZSksXG4gICAgSW50MzJBcnJheTogKHZhbHVlKSA9PlxuICAgICAgdmFsdWUgaW5zdGFuY2VvZiBnbG9iYWwuSW50MzJBcnJheSAmJiB2aWV3VG9CYXNlNjQodmFsdWUpLFxuICAgIE1hcDogKHZhbHVlKSA9PiB2YWx1ZSBpbnN0YW5jZW9mIGdsb2JhbC5NYXAgJiYgQXJyYXkuZnJvbSh2YWx1ZSksXG4gICAgUmVnRXhwOiAodmFsdWUpID0+XG4gICAgICB2YWx1ZSBpbnN0YW5jZW9mIGdsb2JhbC5SZWdFeHAgJiYge1xuICAgICAgICBzb3VyY2U6IHZhbHVlLnNvdXJjZSxcbiAgICAgICAgZmxhZ3M6IHZhbHVlLmZsYWdzLFxuICAgICAgfSxcbiAgICBSZXF1ZXN0OiAodmFsdWUpID0+IHtcbiAgICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgZ2xvYmFsLlJlcXVlc3QpKSByZXR1cm4gZmFsc2U7XG4gICAgICBjb25zdCBkYXRhOiBTZXJpYWxpemFibGVTcGVjaWFsWydSZXF1ZXN0J10gPSB7XG4gICAgICAgIG1ldGhvZDogdmFsdWUubWV0aG9kLFxuICAgICAgICB1cmw6IHZhbHVlLnVybCxcbiAgICAgICAgaGVhZGVyczogdmFsdWUuaGVhZGVycyxcbiAgICAgICAgYm9keTogdmFsdWUuYm9keSxcbiAgICAgICAgZHVwbGV4OiB2YWx1ZS5kdXBsZXgsXG4gICAgICB9O1xuICAgICAgY29uc3QgcmVzcG9uc2VXcml0YWJsZSA9IHZhbHVlW1dFQkhPT0tfUkVTUE9OU0VfV1JJVEFCTEVdO1xuICAgICAgaWYgKHJlc3BvbnNlV3JpdGFibGUpIHtcbiAgICAgICAgZGF0YS5yZXNwb25zZVdyaXRhYmxlID0gcmVzcG9uc2VXcml0YWJsZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBkYXRhO1xuICAgIH0sXG4gICAgUmVzcG9uc2U6ICh2YWx1ZSkgPT4ge1xuICAgICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBnbG9iYWwuUmVzcG9uc2UpKSByZXR1cm4gZmFsc2U7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiB2YWx1ZS50eXBlLFxuICAgICAgICB1cmw6IHZhbHVlLnVybCxcbiAgICAgICAgc3RhdHVzOiB2YWx1ZS5zdGF0dXMsXG4gICAgICAgIHN0YXR1c1RleHQ6IHZhbHVlLnN0YXR1c1RleHQsXG4gICAgICAgIGhlYWRlcnM6IHZhbHVlLmhlYWRlcnMsXG4gICAgICAgIGJvZHk6IHZhbHVlLmJvZHksXG4gICAgICAgIHJlZGlyZWN0ZWQ6IHZhbHVlLnJlZGlyZWN0ZWQsXG4gICAgICB9O1xuICAgIH0sXG4gICAgU2V0OiAodmFsdWUpID0+IHZhbHVlIGluc3RhbmNlb2YgZ2xvYmFsLlNldCAmJiBBcnJheS5mcm9tKHZhbHVlKSxcbiAgICBTdGVwRnVuY3Rpb246ICh2YWx1ZSkgPT4ge1xuICAgICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ2Z1bmN0aW9uJykgcmV0dXJuIGZhbHNlO1xuICAgICAgY29uc3Qgc3RlcElkID0gKHZhbHVlIGFzIGFueSkuc3RlcElkO1xuICAgICAgaWYgKHR5cGVvZiBzdGVwSWQgIT09ICdzdHJpbmcnKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgIC8vIENoZWNrIGlmIHRoZSBzdGVwIGZ1bmN0aW9uIGhhcyBjbG9zdXJlIHZhcmlhYmxlc1xuICAgICAgY29uc3QgY2xvc3VyZVZhcnNGbiA9ICh2YWx1ZSBhcyBhbnkpLl9fY2xvc3VyZVZhcnNGbjtcbiAgICAgIGlmIChjbG9zdXJlVmFyc0ZuICYmIHR5cGVvZiBjbG9zdXJlVmFyc0ZuID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIC8vIEludm9rZSB0aGUgY2xvc3VyZSB2YXJpYWJsZXMgZnVuY3Rpb24gYW5kIHNlcmlhbGl6ZSBhbG9uZyB3aXRoIHN0ZXBJZFxuICAgICAgICBjb25zdCBjbG9zdXJlVmFycyA9IGNsb3N1cmVWYXJzRm4oKTtcbiAgICAgICAgcmV0dXJuIHsgc3RlcElkLCBjbG9zdXJlVmFycyB9O1xuICAgICAgfVxuXG4gICAgICAvLyBObyBjbG9zdXJlIHZhcmlhYmxlcyAtIHJldHVybiBvYmplY3Qgd2l0aCBqdXN0IHN0ZXBJZFxuICAgICAgcmV0dXJuIHsgc3RlcElkIH07XG4gICAgfSxcbiAgICBVUkw6ICh2YWx1ZSkgPT4gdmFsdWUgaW5zdGFuY2VvZiBnbG9iYWwuVVJMICYmIHZhbHVlLmhyZWYsXG4gICAgV29ya2Zsb3dGdW5jdGlvbjogKHZhbHVlKSA9PiB7XG4gICAgICAvLyBPbmx5IG1hdGNoIGZ1bmN0aW9uIHJlZmVyZW5jZXMgd2l0aCBhIHdvcmtmbG93SWQgcHJvcGVydHkgKHNldCBieVxuICAgICAgLy8gdGhlIFNXQyBjb21waWxlciBvbiB3b3JrZmxvdyBmdW5jdGlvbnMpLiBQbGFpbiB7IHdvcmtmbG93SWQgfSBvYmplY3RzXG4gICAgICAvLyBhcmUgTk9UIG1hdGNoZWQg4oCUIHRoaXMgcHJldmVudHMgaW5maW5pdGUgcmVjdXJzaW9uIHNpbmNlIHRoZSByZWR1Y2VkXG4gICAgICAvLyBmb3JtIHsgd29ya2Zsb3dJZCB9IGlzIGEgcGxhaW4gb2JqZWN0LCBub3QgYSBmdW5jdGlvbi5cbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdmdW5jdGlvbicpIHJldHVybiBmYWxzZTtcbiAgICAgIGNvbnN0IHdvcmtmbG93SWQgPSAodmFsdWUgYXMgYW55KS53b3JrZmxvd0lkO1xuICAgICAgaWYgKHR5cGVvZiB3b3JrZmxvd0lkICE9PSAnc3RyaW5nJykgcmV0dXJuIGZhbHNlO1xuICAgICAgcmV0dXJuIHsgd29ya2Zsb3dJZCB9O1xuICAgIH0sXG4gICAgVVJMU2VhcmNoUGFyYW1zOiAodmFsdWUpID0+IHtcbiAgICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgZ2xvYmFsLlVSTFNlYXJjaFBhcmFtcykpIHJldHVybiBmYWxzZTtcblxuICAgICAgLy8gQXZvaWQgcmV0dXJuaW5nIGEgZmFsc3kgdmFsdWUgd2hlbiB0aGUgVVJMU2VhcmNoUGFyYW1zIGlzIGVtcHR5XG4gICAgICBpZiAodmFsdWUuc2l6ZSA9PT0gMCkgcmV0dXJuICcuJztcblxuICAgICAgcmV0dXJuIFN0cmluZyh2YWx1ZSk7XG4gICAgfSxcbiAgICBVaW50OEFycmF5OiAodmFsdWUpID0+XG4gICAgICB2YWx1ZSBpbnN0YW5jZW9mIGdsb2JhbC5VaW50OEFycmF5ICYmIHZpZXdUb0Jhc2U2NCh2YWx1ZSksXG4gICAgVWludDhDbGFtcGVkQXJyYXk6ICh2YWx1ZSkgPT5cbiAgICAgIHZhbHVlIGluc3RhbmNlb2YgZ2xvYmFsLlVpbnQ4Q2xhbXBlZEFycmF5ICYmIHZpZXdUb0Jhc2U2NCh2YWx1ZSksXG4gICAgVWludDE2QXJyYXk6ICh2YWx1ZSkgPT5cbiAgICAgIHZhbHVlIGluc3RhbmNlb2YgZ2xvYmFsLlVpbnQxNkFycmF5ICYmIHZpZXdUb0Jhc2U2NCh2YWx1ZSksXG4gICAgVWludDMyQXJyYXk6ICh2YWx1ZSkgPT5cbiAgICAgIHZhbHVlIGluc3RhbmNlb2YgZ2xvYmFsLlVpbnQzMkFycmF5ICYmIHZpZXdUb0Jhc2U2NCh2YWx1ZSksXG4gIH0gYXMgY29uc3Qgc2F0aXNmaWVzIFBhcnRpYWw8UmVkdWNlcnM+O1xufVxuXG4vKipcbiAqIFJlZHVjZXJzIGZvciBzZXJpYWxpemF0aW9uIGJvdW5kYXJ5IGZyb20gdGhlIGNsaWVudCBzaWRlLCBwYXNzaW5nIGFyZ3VtZW50c1xuICogdG8gdGhlIHdvcmtmbG93IGhhbmRsZXIuXG4gKlxuICogQHBhcmFtIGdsb2JhbFxuICogQHBhcmFtIG9wc1xuICogQHJldHVybnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEV4dGVybmFsUmVkdWNlcnMoXG4gIGdsb2JhbDogUmVjb3JkPHN0cmluZywgYW55PiA9IGdsb2JhbFRoaXMsXG4gIG9wczogUHJvbWlzZTx2b2lkPltdLFxuICBydW5JZDogc3RyaW5nLFxuICBjcnlwdG9LZXk6IEVuY3J5cHRpb25LZXlQYXJhbVxuKTogUmVkdWNlcnMge1xuICByZXR1cm4ge1xuICAgIC4uLmdldENvbW1vblJlZHVjZXJzKGdsb2JhbCksXG5cbiAgICBSZWFkYWJsZVN0cmVhbTogKHZhbHVlKSA9PiB7XG4gICAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIGdsb2JhbC5SZWFkYWJsZVN0cmVhbSkpIHJldHVybiBmYWxzZTtcblxuICAgICAgLy8gU3RyZWFtIG11c3Qgbm90IGJlIGxvY2tlZCB3aGVuIHBhc3NpbmcgYWNyb3NzIGV4ZWN1dGlvbiBib3VuZGFyeVxuICAgICAgaWYgKHZhbHVlLmxvY2tlZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1JlYWRhYmxlU3RyZWFtIGlzIGxvY2tlZCcpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBzdHJlYW1JZCA9ICgoZ2xvYmFsIGFzIGFueSlbU1RBQkxFX1VMSURdIHx8IGRlZmF1bHRVbGlkKSgpO1xuICAgICAgY29uc3QgbmFtZSA9IGBzdHJtXyR7c3RyZWFtSWR9YDtcbiAgICAgIGNvbnN0IHR5cGUgPSBnZXRTdHJlYW1UeXBlKHZhbHVlKTtcblxuICAgICAgY29uc3Qgd3JpdGFibGUgPSBuZXcgV29ya2Zsb3dTZXJ2ZXJXcml0YWJsZVN0cmVhbShydW5JZCwgbmFtZSk7XG4gICAgICBpZiAodHlwZSA9PT0gJ2J5dGVzJykge1xuICAgICAgICBvcHMucHVzaCh2YWx1ZS5waXBlVG8od3JpdGFibGUpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG9wcy5wdXNoKFxuICAgICAgICAgIHZhbHVlXG4gICAgICAgICAgICAucGlwZVRocm91Z2goXG4gICAgICAgICAgICAgIGdldFNlcmlhbGl6ZVN0cmVhbShcbiAgICAgICAgICAgICAgICBnZXRFeHRlcm5hbFJlZHVjZXJzKGdsb2JhbCwgb3BzLCBydW5JZCwgY3J5cHRvS2V5KSxcbiAgICAgICAgICAgICAgICBjcnlwdG9LZXlcbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgLnBpcGVUbyh3cml0YWJsZSlcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgczogU2VyaWFsaXphYmxlU3BlY2lhbFsnUmVhZGFibGVTdHJlYW0nXSA9IHsgbmFtZSB9O1xuICAgICAgaWYgKHR5cGUpIHMudHlwZSA9IHR5cGU7XG4gICAgICByZXR1cm4gcztcbiAgICB9LFxuXG4gICAgV3JpdGFibGVTdHJlYW06ICh2YWx1ZSkgPT4ge1xuICAgICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBnbG9iYWwuV3JpdGFibGVTdHJlYW0pKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgIGNvbnN0IHN0cmVhbUlkID0gKChnbG9iYWwgYXMgYW55KVtTVEFCTEVfVUxJRF0gfHwgZGVmYXVsdFVsaWQpKCk7XG4gICAgICBjb25zdCBuYW1lID0gYHN0cm1fJHtzdHJlYW1JZH1gO1xuXG4gICAgICBjb25zdCByZWFkYWJsZSA9IG5ldyBXb3JrZmxvd1NlcnZlclJlYWRhYmxlU3RyZWFtKHJ1bklkLCBuYW1lKTtcbiAgICAgIG9wcy5wdXNoKHJlYWRhYmxlLnBpcGVUbyh2YWx1ZSkpO1xuXG4gICAgICByZXR1cm4geyBuYW1lIH07XG4gICAgfSxcbiAgfTtcbn1cblxuLyoqXG4gKiBSZWR1Y2VycyBmb3Igc2VyaWFsaXphdGlvbiBib3VuZGFyeSBmcm9tIHdpdGhpbiB0aGUgd29ya2Zsb3cgZXhlY3V0aW9uXG4gKiBlbnZpcm9ubWVudCwgcGFzc2luZyByZXR1cm4gdmFsdWUgdG8gdGhlIGNsaWVudCBzaWRlIGFuZCBpbnRvIHN0ZXAgYXJndW1lbnRzLlxuICpcbiAqIEBwYXJhbSBnbG9iYWxcbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRXb3JrZmxvd1JlZHVjZXJzKFxuICBnbG9iYWw6IFJlY29yZDxzdHJpbmcsIGFueT4gPSBnbG9iYWxUaGlzXG4pOiBSZWR1Y2VycyB7XG4gIHJldHVybiB7XG4gICAgLi4uZ2V0Q29tbW9uUmVkdWNlcnMoZ2xvYmFsKSxcblxuICAgIC8vIFJlYWRhYmxlL1dyaXRhYmxlIHN0cmVhbXMgZnJvbSB3aXRoaW4gdGhlIHdvcmtmbG93IGV4ZWN1dGlvbiBlbnZpcm9ubWVudFxuICAgIC8vIGFyZSBzaW1wbHkgXCJoYW5kbGVzXCIgdGhhdCBjYW4gYmUgcGFzc2VkIGFyb3VuZCB0byBvdGhlciBzdGVwcy5cbiAgICBSZWFkYWJsZVN0cmVhbTogKHZhbHVlKSA9PiB7XG4gICAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIGdsb2JhbC5SZWFkYWJsZVN0cmVhbSkpIHJldHVybiBmYWxzZTtcblxuICAgICAgLy8gQ2hlY2sgaWYgdGhpcyBpcyBhIGZha2Ugc3RyZWFtIHN0b3JpbmcgQm9keUluaXQgZnJvbSBSZXF1ZXN0L1Jlc3BvbnNlIGNvbnN0cnVjdG9yXG4gICAgICBjb25zdCBib2R5SW5pdCA9IHZhbHVlW0JPRFlfSU5JVF9TWU1CT0xdO1xuICAgICAgaWYgKGJvZHlJbml0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgLy8gVGhpcyBpcyBhIGZha2Ugc3RyZWFtIC0gc2VyaWFsaXplIHRoZSBCb2R5SW5pdCBkaXJlY3RseVxuICAgICAgICAvLyBkZXZhbHVlIHdpbGwgaGFuZGxlIHNlcmlhbGl6aW5nIHN0cmluZ3MsIFVpbnQ4QXJyYXksIGV0Yy5cbiAgICAgICAgcmV0dXJuIHsgYm9keUluaXQgfTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbmFtZSA9IHZhbHVlW1NUUkVBTV9OQU1FX1NZTUJPTF07XG4gICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdSZWFkYWJsZVN0cmVhbSBgbmFtZWAgaXMgbm90IHNldCcpO1xuICAgICAgfVxuICAgICAgY29uc3QgczogU2VyaWFsaXphYmxlU3BlY2lhbFsnUmVhZGFibGVTdHJlYW0nXSA9IHsgbmFtZSB9O1xuICAgICAgY29uc3QgdHlwZSA9IHZhbHVlW1NUUkVBTV9UWVBFX1NZTUJPTF07XG4gICAgICBpZiAodHlwZSkgcy50eXBlID0gdHlwZTtcbiAgICAgIHJldHVybiBzO1xuICAgIH0sXG4gICAgV3JpdGFibGVTdHJlYW06ICh2YWx1ZSkgPT4ge1xuICAgICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBnbG9iYWwuV3JpdGFibGVTdHJlYW0pKSByZXR1cm4gZmFsc2U7XG4gICAgICBjb25zdCBuYW1lID0gdmFsdWVbU1RSRUFNX05BTUVfU1lNQk9MXTtcbiAgICAgIGlmICghbmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1dyaXRhYmxlU3RyZWFtIGBuYW1lYCBpcyBub3Qgc2V0Jyk7XG4gICAgICB9XG4gICAgICByZXR1cm4geyBuYW1lIH07XG4gICAgfSxcbiAgfTtcbn1cblxuLyoqXG4gKiBSZWR1Y2VycyBmb3Igc2VyaWFsaXphdGlvbiBib3VuZGFyeSBmcm9tIHdpdGhpbiB0aGUgc3RlcCBleGVjdXRpb25cbiAqIGVudmlyb25tZW50LCBwYXNzaW5nIHJldHVybiB2YWx1ZSB0byB0aGUgd29ya2Zsb3cgaGFuZGxlci5cbiAqXG4gKiBAcGFyYW0gZ2xvYmFsXG4gKiBAcGFyYW0gb3BzXG4gKiBAcGFyYW0gcnVuSWRcbiAqIEByZXR1cm5zXG4gKi9cbmZ1bmN0aW9uIGdldFN0ZXBSZWR1Y2VycyhcbiAgZ2xvYmFsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0gZ2xvYmFsVGhpcyxcbiAgb3BzOiBQcm9taXNlPHZvaWQ+W10sXG4gIHJ1bklkOiBzdHJpbmcsXG4gIGNyeXB0b0tleTogRW5jcnlwdGlvbktleVBhcmFtXG4pOiBSZWR1Y2VycyB7XG4gIHJldHVybiB7XG4gICAgLi4uZ2V0Q29tbW9uUmVkdWNlcnMoZ2xvYmFsKSxcblxuICAgIFJlYWRhYmxlU3RyZWFtOiAodmFsdWUpID0+IHtcbiAgICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgZ2xvYmFsLlJlYWRhYmxlU3RyZWFtKSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgICAvLyBTdHJlYW0gbXVzdCBub3QgYmUgbG9ja2VkIHdoZW4gcGFzc2luZyBhY3Jvc3MgZXhlY3V0aW9uIGJvdW5kYXJ5XG4gICAgICBpZiAodmFsdWUubG9ja2VkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignUmVhZGFibGVTdHJlYW0gaXMgbG9ja2VkJyk7XG4gICAgICB9XG5cbiAgICAgIC8vIENoZWNrIGlmIHRoZSBzdHJlYW0gYWxyZWFkeSBoYXMgdGhlIG5hbWUgc3ltYm9sIHNldCwgaW4gd2hpY2ggY2FzZVxuICAgICAgLy8gaXQncyBhbHJlYWR5IGJlaW5nIHN1bmsgdG8gdGhlIHNlcnZlciBhbmQgd2UgY2FuIGp1c3QgcmV0dXJuIHRoZVxuICAgICAgLy8gbmFtZSBhbmQgdHlwZS5cbiAgICAgIGxldCBuYW1lID0gdmFsdWVbU1RSRUFNX05BTUVfU1lNQk9MXTtcbiAgICAgIGxldCB0eXBlID0gdmFsdWVbU1RSRUFNX1RZUEVfU1lNQk9MXTtcblxuICAgICAgaWYgKCFuYW1lKSB7XG4gICAgICAgIGNvbnN0IHN0cmVhbUlkID0gKChnbG9iYWwgYXMgYW55KVtTVEFCTEVfVUxJRF0gfHwgZGVmYXVsdFVsaWQpKCk7XG4gICAgICAgIG5hbWUgPSBgc3RybV8ke3N0cmVhbUlkfWA7XG4gICAgICAgIHR5cGUgPSBnZXRTdHJlYW1UeXBlKHZhbHVlKTtcblxuICAgICAgICBjb25zdCB3cml0YWJsZSA9IG5ldyBXb3JrZmxvd1NlcnZlcldyaXRhYmxlU3RyZWFtKHJ1bklkLCBuYW1lKTtcbiAgICAgICAgaWYgKHR5cGUgPT09ICdieXRlcycpIHtcbiAgICAgICAgICBvcHMucHVzaCh2YWx1ZS5waXBlVG8od3JpdGFibGUpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBvcHMucHVzaChcbiAgICAgICAgICAgIHZhbHVlXG4gICAgICAgICAgICAgIC5waXBlVGhyb3VnaChcbiAgICAgICAgICAgICAgICBnZXRTZXJpYWxpemVTdHJlYW0oXG4gICAgICAgICAgICAgICAgICBnZXRTdGVwUmVkdWNlcnMoZ2xvYmFsLCBvcHMsIHJ1bklkLCBjcnlwdG9LZXkpLFxuICAgICAgICAgICAgICAgICAgY3J5cHRvS2V5XG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgIC5waXBlVG8od3JpdGFibGUpXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCBzOiBTZXJpYWxpemFibGVTcGVjaWFsWydSZWFkYWJsZVN0cmVhbSddID0geyBuYW1lIH07XG4gICAgICBpZiAodHlwZSkgcy50eXBlID0gdHlwZTtcbiAgICAgIHJldHVybiBzO1xuICAgIH0sXG5cbiAgICBXcml0YWJsZVN0cmVhbTogKHZhbHVlKSA9PiB7XG4gICAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIGdsb2JhbC5Xcml0YWJsZVN0cmVhbSkpIHJldHVybiBmYWxzZTtcblxuICAgICAgbGV0IG5hbWUgPSB2YWx1ZVtTVFJFQU1fTkFNRV9TWU1CT0xdO1xuICAgICAgaWYgKCFuYW1lKSB7XG4gICAgICAgIGNvbnN0IHN0cmVhbUlkID0gKChnbG9iYWwgYXMgYW55KVtTVEFCTEVfVUxJRF0gfHwgZGVmYXVsdFVsaWQpKCk7XG4gICAgICAgIG5hbWUgPSBgc3RybV8ke3N0cmVhbUlkfWA7XG4gICAgICAgIG9wcy5wdXNoKFxuICAgICAgICAgIG5ldyBXb3JrZmxvd1NlcnZlclJlYWRhYmxlU3RyZWFtKHJ1bklkLCBuYW1lKVxuICAgICAgICAgICAgLnBpcGVUaHJvdWdoKFxuICAgICAgICAgICAgICBnZXREZXNlcmlhbGl6ZVN0cmVhbShcbiAgICAgICAgICAgICAgICBnZXRTdGVwUmV2aXZlcnMoZ2xvYmFsLCBvcHMsIHJ1bklkLCBjcnlwdG9LZXkpLFxuICAgICAgICAgICAgICAgIGNyeXB0b0tleVxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICApXG4gICAgICAgICAgICAucGlwZVRvKHZhbHVlKVxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4geyBuYW1lIH07XG4gICAgfSxcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldENvbW1vblJldml2ZXJzKGdsb2JhbDogUmVjb3JkPHN0cmluZywgYW55PiA9IGdsb2JhbFRoaXMpIHtcbiAgZnVuY3Rpb24gcmV2aXZlQXJyYXlCdWZmZXIodmFsdWU6IHN0cmluZykge1xuICAgIC8vIEhhbmRsZSBzZW50aW5lbCB2YWx1ZSBmb3IgemVyby1sZW5ndGggYnVmZmVyc1xuICAgIGNvbnN0IGJhc2U2NCA9IHZhbHVlID09PSAnLicgPyAnJyA6IHZhbHVlO1xuICAgIGNvbnN0IGJ1ZmZlciA9IEJ1ZmZlci5mcm9tKGJhc2U2NCwgJ2Jhc2U2NCcpO1xuICAgIGNvbnN0IGFycmF5QnVmZmVyID0gbmV3IGdsb2JhbC5BcnJheUJ1ZmZlcihidWZmZXIubGVuZ3RoKTtcbiAgICBjb25zdCB1aW50OEFycmF5ID0gbmV3IGdsb2JhbC5VaW50OEFycmF5KGFycmF5QnVmZmVyKTtcbiAgICB1aW50OEFycmF5LnNldChidWZmZXIpO1xuICAgIHJldHVybiBhcnJheUJ1ZmZlcjtcbiAgfVxuICByZXR1cm4ge1xuICAgIEFycmF5QnVmZmVyOiByZXZpdmVBcnJheUJ1ZmZlcixcbiAgICBCaWdJbnQ6ICh2YWx1ZTogc3RyaW5nKSA9PiBnbG9iYWwuQmlnSW50KHZhbHVlKSxcbiAgICBCaWdJbnQ2NEFycmF5OiAodmFsdWU6IHN0cmluZykgPT4ge1xuICAgICAgY29uc3QgYWIgPSByZXZpdmVBcnJheUJ1ZmZlcih2YWx1ZSk7XG4gICAgICByZXR1cm4gbmV3IGdsb2JhbC5CaWdJbnQ2NEFycmF5KGFiKTtcbiAgICB9LFxuICAgIEJpZ1VpbnQ2NEFycmF5OiAodmFsdWU6IHN0cmluZykgPT4ge1xuICAgICAgY29uc3QgYWIgPSByZXZpdmVBcnJheUJ1ZmZlcih2YWx1ZSk7XG4gICAgICByZXR1cm4gbmV3IGdsb2JhbC5CaWdVaW50NjRBcnJheShhYik7XG4gICAgfSxcbiAgICBEYXRlOiAodmFsdWUpID0+IG5ldyBnbG9iYWwuRGF0ZSh2YWx1ZSksXG4gICAgRE9NRXhjZXB0aW9uOiAodmFsdWUpID0+IHtcbiAgICAgIGNvbnN0IGVycm9yID0gbmV3IGdsb2JhbC5ET01FeGNlcHRpb24odmFsdWUubWVzc2FnZSwgdmFsdWUubmFtZSk7XG4gICAgICBpZiAodmFsdWUuc3RhY2sgIT09IHVuZGVmaW5lZCkgZXJyb3Iuc3RhY2sgPSB2YWx1ZS5zdGFjaztcbiAgICAgIC8vIERPTUV4Y2VwdGlvbidzIGNvbnN0cnVjdG9yIGRvZXNuJ3QgYWNjZXB0IGEgY2F1c2Ugb3B0aW9uLCBzb1xuICAgICAgLy8gd2Ugc2V0IGl0IG1hbnVhbGx5IHdoZW4gcHJlc2VudCBpbiB0aGUgc2VyaWFsaXplZCBkYXRhLlxuICAgICAgaWYgKCdjYXVzZScgaW4gdmFsdWUpIGVycm9yLmNhdXNlID0gdmFsdWUuY2F1c2U7XG4gICAgICByZXR1cm4gZXJyb3I7XG4gICAgfSxcbiAgICBFcnJvcjogKHZhbHVlKSA9PiB7XG4gICAgICBjb25zdCBlcnJvciA9IG5ldyBnbG9iYWwuRXJyb3IodmFsdWUubWVzc2FnZSk7XG4gICAgICBlcnJvci5uYW1lID0gdmFsdWUubmFtZTtcbiAgICAgIGVycm9yLnN0YWNrID0gdmFsdWUuc3RhY2s7XG4gICAgICByZXR1cm4gZXJyb3I7XG4gICAgfSxcbiAgICBGbG9hdDMyQXJyYXk6ICh2YWx1ZTogc3RyaW5nKSA9PiB7XG4gICAgICBjb25zdCBhYiA9IHJldml2ZUFycmF5QnVmZmVyKHZhbHVlKTtcbiAgICAgIHJldHVybiBuZXcgZ2xvYmFsLkZsb2F0MzJBcnJheShhYik7XG4gICAgfSxcbiAgICBGbG9hdDY0QXJyYXk6ICh2YWx1ZTogc3RyaW5nKSA9PiB7XG4gICAgICBjb25zdCBhYiA9IHJldml2ZUFycmF5QnVmZmVyKHZhbHVlKTtcbiAgICAgIHJldHVybiBuZXcgZ2xvYmFsLkZsb2F0NjRBcnJheShhYik7XG4gICAgfSxcbiAgICBIZWFkZXJzOiAodmFsdWUpID0+IG5ldyBnbG9iYWwuSGVhZGVycyh2YWx1ZSksXG4gICAgSW50OEFycmF5OiAodmFsdWU6IHN0cmluZykgPT4ge1xuICAgICAgY29uc3QgYWIgPSByZXZpdmVBcnJheUJ1ZmZlcih2YWx1ZSk7XG4gICAgICByZXR1cm4gbmV3IGdsb2JhbC5JbnQ4QXJyYXkoYWIpO1xuICAgIH0sXG4gICAgSW50MTZBcnJheTogKHZhbHVlOiBzdHJpbmcpID0+IHtcbiAgICAgIGNvbnN0IGFiID0gcmV2aXZlQXJyYXlCdWZmZXIodmFsdWUpO1xuICAgICAgcmV0dXJuIG5ldyBnbG9iYWwuSW50MTZBcnJheShhYik7XG4gICAgfSxcbiAgICBJbnQzMkFycmF5OiAodmFsdWU6IHN0cmluZykgPT4ge1xuICAgICAgY29uc3QgYWIgPSByZXZpdmVBcnJheUJ1ZmZlcih2YWx1ZSk7XG4gICAgICByZXR1cm4gbmV3IGdsb2JhbC5JbnQzMkFycmF5KGFiKTtcbiAgICB9LFxuICAgIE1hcDogKHZhbHVlKSA9PiBuZXcgZ2xvYmFsLk1hcCh2YWx1ZSksXG4gICAgUmVnRXhwOiAodmFsdWUpID0+IG5ldyBnbG9iYWwuUmVnRXhwKHZhbHVlLnNvdXJjZSwgdmFsdWUuZmxhZ3MpLFxuICAgIENsYXNzOiAodmFsdWUpID0+IHtcbiAgICAgIGNvbnN0IGNsYXNzSWQgPSB2YWx1ZS5jbGFzc0lkO1xuICAgICAgLy8gUGFzcyB0aGUgZ2xvYmFsIG9iamVjdCB0byBzdXBwb3J0IFZNIGNvbnRleHRzIHdoZXJlIGNsYXNzZXMgYXJlIHJlZ2lzdGVyZWRcbiAgICAgIC8vIG9uIHRoZSBWTSdzIGdsb2JhbCByYXRoZXIgdGhhbiB0aGUgaG9zdCdzIGdsb2JhbFRoaXNcbiAgICAgIGNvbnN0IGNscyA9IGdldFNlcmlhbGl6YXRpb25DbGFzcyhjbGFzc0lkLCBnbG9iYWwpO1xuICAgICAgaWYgKCFjbHMpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBDbGFzcyBcIiR7Y2xhc3NJZH1cIiBub3QgZm91bmQuIE1ha2Ugc3VyZSB0aGUgY2xhc3MgaXMgcmVnaXN0ZXJlZCB3aXRoIHJlZ2lzdGVyU2VyaWFsaXphdGlvbkNsYXNzLmBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBjbHM7XG4gICAgfSxcbiAgICBJbnN0YW5jZTogKHZhbHVlKSA9PiB7XG4gICAgICBjb25zdCBjbGFzc0lkID0gdmFsdWUuY2xhc3NJZDtcbiAgICAgIGNvbnN0IGRhdGEgPSB2YWx1ZS5kYXRhO1xuXG4gICAgICAvLyBMb29rIHVwIHRoZSBjbGFzcyBieSBjbGFzc0lkIGZyb20gdGhlIHJlZ2lzdHJ5XG4gICAgICAvLyBQYXNzIHRoZSBnbG9iYWwgb2JqZWN0IHRvIHN1cHBvcnQgVk0gY29udGV4dHMgd2hlcmUgY2xhc3NlcyBhcmUgcmVnaXN0ZXJlZFxuICAgICAgLy8gb24gdGhlIFZNJ3MgZ2xvYmFsIHJhdGhlciB0aGFuIHRoZSBob3N0J3MgZ2xvYmFsVGhpc1xuICAgICAgY29uc3QgY2xzID0gZ2V0U2VyaWFsaXphdGlvbkNsYXNzKGNsYXNzSWQsIGdsb2JhbCk7XG5cbiAgICAgIGlmICghY2xzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgQ2xhc3MgXCIke2NsYXNzSWR9XCIgbm90IGZvdW5kLiBNYWtlIHN1cmUgdGhlIGNsYXNzIGlzIHJlZ2lzdGVyZWQgd2l0aCByZWdpc3RlclNlcmlhbGl6YXRpb25DbGFzcy5gXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIC8vIEdldCB0aGUgZGVzZXJpYWxpemVyIGZyb20gdGhlIGNsYXNzXG4gICAgICBjb25zdCBkZXNlcmlhbGl6ZSA9IChjbHMgYXMgYW55KVtXT1JLRkxPV19ERVNFUklBTElaRV07XG4gICAgICBpZiAodHlwZW9mIGRlc2VyaWFsaXplICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgQ2xhc3MgXCIke2NsYXNzSWR9XCIgZG9lcyBub3QgaGF2ZSBhIHN0YXRpYyAke1N0cmluZyhXT1JLRkxPV19ERVNFUklBTElaRSl9IG1ldGhvZC5gXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIC8vIERlc2VyaWFsaXplIHRoZSBpbnN0YW5jZSB1c2luZyB0aGUgY3VzdG9tIGRlc2VyaWFsaXplclxuICAgICAgcmV0dXJuIGRlc2VyaWFsaXplLmNhbGwoY2xzLCBkYXRhKTtcbiAgICB9LFxuICAgIFNldDogKHZhbHVlKSA9PiBuZXcgZ2xvYmFsLlNldCh2YWx1ZSksXG4gICAgVVJMOiAodmFsdWUpID0+IG5ldyBnbG9iYWwuVVJMKHZhbHVlKSxcbiAgICBVUkxTZWFyY2hQYXJhbXM6ICh2YWx1ZSkgPT5cbiAgICAgIG5ldyBnbG9iYWwuVVJMU2VhcmNoUGFyYW1zKHZhbHVlID09PSAnLicgPyAnJyA6IHZhbHVlKSxcbiAgICBVaW50OEFycmF5OiAodmFsdWU6IHN0cmluZykgPT4ge1xuICAgICAgY29uc3QgYWIgPSByZXZpdmVBcnJheUJ1ZmZlcih2YWx1ZSk7XG4gICAgICByZXR1cm4gbmV3IGdsb2JhbC5VaW50OEFycmF5KGFiKTtcbiAgICB9LFxuICAgIFVpbnQ4Q2xhbXBlZEFycmF5OiAodmFsdWU6IHN0cmluZykgPT4ge1xuICAgICAgY29uc3QgYWIgPSByZXZpdmVBcnJheUJ1ZmZlcih2YWx1ZSk7XG4gICAgICByZXR1cm4gbmV3IGdsb2JhbC5VaW50OENsYW1wZWRBcnJheShhYik7XG4gICAgfSxcbiAgICBVaW50MTZBcnJheTogKHZhbHVlOiBzdHJpbmcpID0+IHtcbiAgICAgIGNvbnN0IGFiID0gcmV2aXZlQXJyYXlCdWZmZXIodmFsdWUpO1xuICAgICAgcmV0dXJuIG5ldyBnbG9iYWwuVWludDE2QXJyYXkoYWIpO1xuICAgIH0sXG4gICAgVWludDMyQXJyYXk6ICh2YWx1ZTogc3RyaW5nKSA9PiB7XG4gICAgICBjb25zdCBhYiA9IHJldml2ZUFycmF5QnVmZmVyKHZhbHVlKTtcbiAgICAgIHJldHVybiBuZXcgZ2xvYmFsLlVpbnQzMkFycmF5KGFiKTtcbiAgICB9LFxuICB9IGFzIGNvbnN0IHNhdGlzZmllcyBQYXJ0aWFsPFJldml2ZXJzPjtcbn1cblxuLyoqXG4gKiBSZXZpdmVycyBmb3IgZGVzZXJpYWxpemF0aW9uIGJvdW5kYXJ5IGZyb20gdGhlIGNsaWVudCBzaWRlLFxuICogcmVjZWl2aW5nIHRoZSByZXR1cm4gdmFsdWUgZnJvbSB0aGUgd29ya2Zsb3cgaGFuZGxlci5cbiAqXG4gKiBAcGFyYW0gZ2xvYmFsXG4gKiBAcGFyYW0gb3BzXG4gKiBAcGFyYW0gcnVuSWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEV4dGVybmFsUmV2aXZlcnMoXG4gIGdsb2JhbDogUmVjb3JkPHN0cmluZywgYW55PiA9IGdsb2JhbFRoaXMsXG4gIG9wczogUHJvbWlzZTx2b2lkPltdLFxuICBydW5JZDogc3RyaW5nLFxuICBjcnlwdG9LZXk6IEVuY3J5cHRpb25LZXlQYXJhbVxuKTogUmV2aXZlcnMge1xuICByZXR1cm4ge1xuICAgIC4uLmdldENvbW1vblJldml2ZXJzKGdsb2JhbCksXG5cbiAgICAvLyBTdGVwRnVuY3Rpb24gc2hvdWxkIG5vdCBiZSByZXR1cm5lZCBmcm9tIHdvcmtmbG93cyB0byBjbGllbnRzXG4gICAgU3RlcEZ1bmN0aW9uOiAoKSA9PiB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICdTdGVwIGZ1bmN0aW9ucyBjYW5ub3QgYmUgZGVzZXJpYWxpemVkIGluIGNsaWVudCBjb250ZXh0LiBTdGVwIGZ1bmN0aW9ucyBzaG91bGQgbm90IGJlIHJldHVybmVkIGZyb20gd29ya2Zsb3dzLidcbiAgICAgICk7XG4gICAgfSxcblxuICAgIFdvcmtmbG93RnVuY3Rpb246ICh2YWx1ZSkgPT5cbiAgICAgIE9iamVjdC5hc3NpZ24oXG4gICAgICAgICgpID0+IHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAnV29ya2Zsb3cgZnVuY3Rpb25zIGNhbm5vdCBiZSBjYWxsZWQgZGlyZWN0bHkuIFVzZSBzdGFydCgpIHRvIGludm9rZSB0aGVtLidcbiAgICAgICAgICApO1xuICAgICAgICB9LFxuICAgICAgICB7IHdvcmtmbG93SWQ6IHZhbHVlLndvcmtmbG93SWQgfVxuICAgICAgKSxcblxuICAgIFJlcXVlc3Q6ICh2YWx1ZSkgPT4ge1xuICAgICAgcmV0dXJuIG5ldyBnbG9iYWwuUmVxdWVzdCh2YWx1ZS51cmwsIHtcbiAgICAgICAgbWV0aG9kOiB2YWx1ZS5tZXRob2QsXG4gICAgICAgIGhlYWRlcnM6IG5ldyBnbG9iYWwuSGVhZGVycyh2YWx1ZS5oZWFkZXJzKSxcbiAgICAgICAgYm9keTogdmFsdWUuYm9keSxcbiAgICAgICAgZHVwbGV4OiB2YWx1ZS5kdXBsZXgsXG4gICAgICB9KTtcbiAgICB9LFxuICAgIFJlc3BvbnNlOiAodmFsdWUpID0+IHtcbiAgICAgIC8vIE5vdGU6IFJlc3BvbnNlIGNvbnN0cnVjdG9yIG9ubHkgYWNjZXB0cyBzdGF0dXMsIHN0YXR1c1RleHQsIGFuZCBoZWFkZXJzXG4gICAgICAvLyBUaGUgdHlwZSwgdXJsLCBhbmQgcmVkaXJlY3RlZCBwcm9wZXJ0aWVzIGFyZSByZWFkLW9ubHkgYW5kIHNldCBieSB0aGUgY29uc3RydWN0b3JcbiAgICAgIHJldHVybiBuZXcgZ2xvYmFsLlJlc3BvbnNlKHZhbHVlLmJvZHksIHtcbiAgICAgICAgc3RhdHVzOiB2YWx1ZS5zdGF0dXMsXG4gICAgICAgIHN0YXR1c1RleHQ6IHZhbHVlLnN0YXR1c1RleHQsXG4gICAgICAgIGhlYWRlcnM6IG5ldyBnbG9iYWwuSGVhZGVycyh2YWx1ZS5oZWFkZXJzKSxcbiAgICAgIH0pO1xuICAgIH0sXG4gICAgUmVhZGFibGVTdHJlYW06ICh2YWx1ZSkgPT4ge1xuICAgICAgLy8gSWYgdGhpcyBoYXMgYm9keUluaXQsIGl0IGNhbWUgZnJvbSBhIFJlc3BvbnNlIGNvbnN0cnVjdG9yXG4gICAgICAvLyBDb252ZXJ0IGl0IHRvIGEgUkVBTCBzdHJlYW0gbm93IHRoYXQgd2UncmUgb3V0c2lkZSB0aGUgd29ya2Zsb3dcbiAgICAgIGlmICgnYm9keUluaXQnIGluIHZhbHVlKSB7XG4gICAgICAgIGNvbnN0IGJvZHlJbml0ID0gdmFsdWUuYm9keUluaXQ7XG4gICAgICAgIC8vIFVzZSB0aGUgbmF0aXZlIFJlc3BvbnNlIGNvbnN0cnVjdG9yIHRvIHByb3Blcmx5IGNvbnZlcnQgQm9keUluaXQgdG8gUmVhZGFibGVTdHJlYW1cbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBuZXcgZ2xvYmFsLlJlc3BvbnNlKGJvZHlJbml0KTtcbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmJvZHk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJlYWRhYmxlID0gbmV3IFdvcmtmbG93U2VydmVyUmVhZGFibGVTdHJlYW0oXG4gICAgICAgIHJ1bklkLFxuICAgICAgICB2YWx1ZS5uYW1lLFxuICAgICAgICB2YWx1ZS5zdGFydEluZGV4XG4gICAgICApO1xuICAgICAgaWYgKHZhbHVlLnR5cGUgPT09ICdieXRlcycpIHtcbiAgICAgICAgLy8gRm9yIGJ5dGUgc3RyZWFtcywgdXNlIGZsdXNoYWJsZSBwaXBlIHdpdGggbG9jayBwb2xsaW5nXG4gICAgICAgIGNvbnN0IHN0YXRlID0gY3JlYXRlRmx1c2hhYmxlU3RhdGUoKTtcbiAgICAgICAgb3BzLnB1c2goc3RhdGUucHJvbWlzZSk7XG5cbiAgICAgICAgLy8gQ3JlYXRlIGFuIGlkZW50aXR5IHRyYW5zZm9ybSB0byBnaXZlIHRoZSB1c2VyIGEgcmVhZGFibGVcbiAgICAgICAgY29uc3QgeyByZWFkYWJsZTogdXNlclJlYWRhYmxlLCB3cml0YWJsZSB9ID1cbiAgICAgICAgICBuZXcgZ2xvYmFsLlRyYW5zZm9ybVN0cmVhbSgpO1xuXG4gICAgICAgIC8vIFN0YXJ0IHRoZSBmbHVzaGFibGUgcGlwZSBpbiB0aGUgYmFja2dyb3VuZFxuICAgICAgICBmbHVzaGFibGVQaXBlKHJlYWRhYmxlLCB3cml0YWJsZSwgc3RhdGUpLmNhdGNoKCgpID0+IHtcbiAgICAgICAgICAvLyBFcnJvcnMgYXJlIGhhbmRsZWQgdmlhIHN0YXRlLnJlamVjdFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBTdGFydCBwb2xsaW5nIHRvIGRldGVjdCB3aGVuIHVzZXIgcmVsZWFzZXMgbG9ja1xuICAgICAgICBwb2xsUmVhZGFibGVMb2NrKHVzZXJSZWFkYWJsZSwgc3RhdGUpO1xuXG4gICAgICAgIHJldHVybiB1c2VyUmVhZGFibGU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCB0cmFuc2Zvcm0gPSBnZXREZXNlcmlhbGl6ZVN0cmVhbShcbiAgICAgICAgICBnZXRFeHRlcm5hbFJldml2ZXJzKGdsb2JhbCwgb3BzLCBydW5JZCwgY3J5cHRvS2V5KSxcbiAgICAgICAgICBjcnlwdG9LZXlcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3Qgc3RhdGUgPSBjcmVhdGVGbHVzaGFibGVTdGF0ZSgpO1xuICAgICAgICBvcHMucHVzaChzdGF0ZS5wcm9taXNlKTtcblxuICAgICAgICAvLyBTdGFydCB0aGUgZmx1c2hhYmxlIHBpcGUgaW4gdGhlIGJhY2tncm91bmRcbiAgICAgICAgZmx1c2hhYmxlUGlwZShyZWFkYWJsZSwgdHJhbnNmb3JtLndyaXRhYmxlLCBzdGF0ZSkuY2F0Y2goKCkgPT4ge1xuICAgICAgICAgIC8vIEVycm9ycyBhcmUgaGFuZGxlZCB2aWEgc3RhdGUucmVqZWN0XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFN0YXJ0IHBvbGxpbmcgdG8gZGV0ZWN0IHdoZW4gdXNlciByZWxlYXNlcyBsb2NrXG4gICAgICAgIHBvbGxSZWFkYWJsZUxvY2sodHJhbnNmb3JtLnJlYWRhYmxlLCBzdGF0ZSk7XG5cbiAgICAgICAgcmV0dXJuIHRyYW5zZm9ybS5yZWFkYWJsZTtcbiAgICAgIH1cbiAgICB9LFxuICAgIFdyaXRhYmxlU3RyZWFtOiAodmFsdWUpID0+IHtcbiAgICAgIGNvbnN0IHNlcmlhbGl6ZSA9IGdldFNlcmlhbGl6ZVN0cmVhbShcbiAgICAgICAgZ2V0RXh0ZXJuYWxSZWR1Y2VycyhnbG9iYWwsIG9wcywgcnVuSWQsIGNyeXB0b0tleSksXG4gICAgICAgIGNyeXB0b0tleVxuICAgICAgKTtcbiAgICAgIGNvbnN0IHNlcnZlcldyaXRhYmxlID0gbmV3IFdvcmtmbG93U2VydmVyV3JpdGFibGVTdHJlYW0oXG4gICAgICAgIHJ1bklkLFxuICAgICAgICB2YWx1ZS5uYW1lXG4gICAgICApO1xuXG4gICAgICAvLyBDcmVhdGUgZmx1c2hhYmxlIHN0YXRlIGZvciB0aGlzIHN0cmVhbVxuICAgICAgY29uc3Qgc3RhdGUgPSBjcmVhdGVGbHVzaGFibGVTdGF0ZSgpO1xuICAgICAgb3BzLnB1c2goc3RhdGUucHJvbWlzZSk7XG5cbiAgICAgIC8vIFN0YXJ0IHRoZSBmbHVzaGFibGUgcGlwZSBpbiB0aGUgYmFja2dyb3VuZFxuICAgICAgZmx1c2hhYmxlUGlwZShzZXJpYWxpemUucmVhZGFibGUsIHNlcnZlcldyaXRhYmxlLCBzdGF0ZSkuY2F0Y2goKCkgPT4ge1xuICAgICAgICAvLyBFcnJvcnMgYXJlIGhhbmRsZWQgdmlhIHN0YXRlLnJlamVjdFxuICAgICAgfSk7XG5cbiAgICAgIC8vIFN0YXJ0IHBvbGxpbmcgdG8gZGV0ZWN0IHdoZW4gdXNlciByZWxlYXNlcyBsb2NrXG4gICAgICBwb2xsV3JpdGFibGVMb2NrKHNlcmlhbGl6ZS53cml0YWJsZSwgc3RhdGUpO1xuXG4gICAgICByZXR1cm4gc2VyaWFsaXplLndyaXRhYmxlO1xuICAgIH0sXG4gIH07XG59XG5cbi8qKlxuICogUmV2aXZlcnMgZm9yIGRlc2VyaWFsaXphdGlvbiBib3VuZGFyeSBmcm9tIHdpdGhpbiB0aGUgd29ya2Zsb3cgZXhlY3V0aW9uXG4gKiBlbnZpcm9ubWVudCwgcmVjZWl2aW5nIGFyZ3VtZW50cyBmcm9tIHRoZSBjbGllbnQgc2lkZSwgYW5kIHJldHVybiB2YWx1ZXNcbiAqIGZyb20gdGhlIHN0ZXBzLlxuICpcbiAqIEBwYXJhbSBnbG9iYWxcbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRXb3JrZmxvd1Jldml2ZXJzKFxuICBnbG9iYWw6IFJlY29yZDxzdHJpbmcsIGFueT4gPSBnbG9iYWxUaGlzXG4pOiBSZXZpdmVycyB7XG4gIC8vIEdldCB0aGUgdXNlU3RlcCBmdW5jdGlvbiBmcm9tIHRoZSBWTSdzIGdsb2JhbFRoaXNcbiAgLy8gVGhpcyBpcyBzZXQgdXAgYnkgdGhlIHdvcmtmbG93IHJ1bm5lciBpbiB3b3JrZmxvdy50c1xuICAvLyBVc2UgU3ltYm9sLmZvciBkaXJlY3RseSB0byBhY2Nlc3MgdGhlIHN5bWJvbCBvbiB0aGUgZ2xvYmFsIG9iamVjdFxuICBjb25zdCB1c2VTdGVwID0gKGdsb2JhbCBhcyBhbnkpW1N5bWJvbC5mb3IoJ1dPUktGTE9XX1VTRV9TVEVQJyldIGFzXG4gICAgfCAoKFxuICAgICAgICBzdGVwSWQ6IHN0cmluZyxcbiAgICAgICAgY2xvc3VyZVZhcnNGbj86ICgpID0+IFJlY29yZDxzdHJpbmcsIHVua25vd24+XG4gICAgICApID0+ICguLi5hcmdzOiB1bmtub3duW10pID0+IFByb21pc2U8dW5rbm93bj4pXG4gICAgfCB1bmRlZmluZWQ7XG5cbiAgcmV0dXJuIHtcbiAgICAuLi5nZXRDb21tb25SZXZpdmVycyhnbG9iYWwpLFxuICAgIC8vIFN0ZXBGdW5jdGlvbiByZXZpdmVyIGZvciB3b3JrZmxvdyBjb250ZXh0IC0gcmV0dXJucyB1c2VTdGVwIHdyYXBwZXJcbiAgICAvLyBUaGlzIGFsbG93cyBzdGVwIGZ1bmN0aW9ucyBwYXNzZWQgYXMgYXJndW1lbnRzIHRvIHN0YXJ0KCkgdG8gYmUgY2FsbGVkIGRpcmVjdGx5XG4gICAgLy8gZnJvbSB3b3JrZmxvdyBjb2RlLCBqdXN0IGxpa2Ugc3RlcCBmdW5jdGlvbnMgZGVmaW5lZCBpbiB0aGUgc2FtZSBmaWxlXG4gICAgU3RlcEZ1bmN0aW9uOiAodmFsdWUpID0+IHtcbiAgICAgIGNvbnN0IHN0ZXBJZCA9IHZhbHVlLnN0ZXBJZDtcbiAgICAgIGNvbnN0IGNsb3N1cmVWYXJzID0gdmFsdWUuY2xvc3VyZVZhcnM7XG5cbiAgICAgIGlmICghdXNlU3RlcCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgJ1dPUktGTE9XX1VTRV9TVEVQIG5vdCBmb3VuZCBvbiBnbG9iYWwgb2JqZWN0LiBTdGVwIGZ1bmN0aW9ucyBjYW5ub3QgYmUgZGVzZXJpYWxpemVkIG91dHNpZGUgd29ya2Zsb3cgY29udGV4dC4nXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGlmIChjbG9zdXJlVmFycykge1xuICAgICAgICAvLyBGb3Igc3RlcCBmdW5jdGlvbnMgd2l0aCBjbG9zdXJlIHZhcmlhYmxlcywgY3JlYXRlIGEgd3JhcHBlciB0aGF0IHByb3ZpZGVzIHRoZW1cbiAgICAgICAgcmV0dXJuIHVzZVN0ZXAoc3RlcElkLCAoKSA9PiBjbG9zdXJlVmFycyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdXNlU3RlcChzdGVwSWQpO1xuICAgIH0sXG4gICAgUmVxdWVzdDogKHZhbHVlKSA9PiB7XG4gICAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YodmFsdWUsIGdsb2JhbC5SZXF1ZXN0LnByb3RvdHlwZSk7XG4gICAgICBjb25zdCByZXNwb25zZVdyaXRhYmxlID0gdmFsdWUucmVzcG9uc2VXcml0YWJsZTtcbiAgICAgIGlmIChyZXNwb25zZVdyaXRhYmxlKSB7XG4gICAgICAgICh2YWx1ZSBhcyBhbnkpW1dFQkhPT0tfUkVTUE9OU0VfV1JJVEFCTEVdID0gcmVzcG9uc2VXcml0YWJsZTtcbiAgICAgICAgZGVsZXRlIHZhbHVlLnJlc3BvbnNlV3JpdGFibGU7XG4gICAgICAgICh2YWx1ZSBhcyBhbnkpLnJlc3BvbmRXaXRoID0gKCkgPT4ge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICdgcmVzcG9uZFdpdGgoKWAgbXVzdCBiZSBjYWxsZWQgZnJvbSB3aXRoaW4gYSBzdGVwIGZ1bmN0aW9uJ1xuICAgICAgICAgICk7XG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfSxcbiAgICAvLyBXb3JrZmxvdyBmdW5jdGlvbiByZXZpdmVyIGZvciB3b3JrZmxvdyBjb250ZXh0IOKAlCByZXR1cm5zIGEgZnVuY3Rpb24tbGlrZVxuICAgIC8vIG9iamVjdCB3aXRoIC53b3JrZmxvd0lkIHRoYXQgbWltaWNzIHdoYXQgdGhlIFNXQyBjb21waWxlciBwcm9kdWNlcyxcbiAgICBXb3JrZmxvd0Z1bmN0aW9uOiAodmFsdWUpID0+XG4gICAgICBPYmplY3QuYXNzaWduKFxuICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgJ1dvcmtmbG93IGZ1bmN0aW9ucyBjYW5ub3QgYmUgY2FsbGVkIGRpcmVjdGx5LiBVc2Ugc3RhcnQoKSB0byBpbnZva2UgdGhlbS4nXG4gICAgICAgICAgKTtcbiAgICAgICAgfSxcbiAgICAgICAgeyB3b3JrZmxvd0lkOiB2YWx1ZS53b3JrZmxvd0lkIH1cbiAgICAgICksXG4gICAgUmVzcG9uc2U6ICh2YWx1ZSkgPT4ge1xuICAgICAgT2JqZWN0LnNldFByb3RvdHlwZU9mKHZhbHVlLCBnbG9iYWwuUmVzcG9uc2UucHJvdG90eXBlKTtcbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9LFxuICAgIFJlYWRhYmxlU3RyZWFtOiAodmFsdWUpID0+IHtcbiAgICAgIC8vIENoZWNrIGlmIHRoaXMgaXMgYSBCb2R5SW5pdCB0aGF0IHNob3VsZCBiZSB3cmFwcGVkIGluIGEgZmFrZSBzdHJlYW1cbiAgICAgIGlmICgnYm9keUluaXQnIGluIHZhbHVlKSB7XG4gICAgICAgIC8vIFJlY3JlYXRlIHRoZSBmYWtlIHN0cmVhbSB3aXRoIHRoZSBCb2R5SW5pdFxuICAgICAgICByZXR1cm4gT2JqZWN0LmNyZWF0ZShnbG9iYWwuUmVhZGFibGVTdHJlYW0ucHJvdG90eXBlLCB7XG4gICAgICAgICAgW0JPRFlfSU5JVF9TWU1CT0xdOiB7XG4gICAgICAgICAgICB2YWx1ZTogdmFsdWUuYm9keUluaXQsXG4gICAgICAgICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIC8vIFJlZ3VsYXIgc3RyZWFtIGhhbmRsaW5nXG4gICAgICByZXR1cm4gT2JqZWN0LmNyZWF0ZShnbG9iYWwuUmVhZGFibGVTdHJlYW0ucHJvdG90eXBlLCB7XG4gICAgICAgIFtTVFJFQU1fTkFNRV9TWU1CT0xdOiB7XG4gICAgICAgICAgdmFsdWU6IHZhbHVlLm5hbWUsXG4gICAgICAgICAgd3JpdGFibGU6IGZhbHNlLFxuICAgICAgICB9LFxuICAgICAgICBbU1RSRUFNX1RZUEVfU1lNQk9MXToge1xuICAgICAgICAgIHZhbHVlOiB2YWx1ZS50eXBlLFxuICAgICAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0sXG4gICAgV3JpdGFibGVTdHJlYW06ICh2YWx1ZSkgPT4ge1xuICAgICAgcmV0dXJuIE9iamVjdC5jcmVhdGUoZ2xvYmFsLldyaXRhYmxlU3RyZWFtLnByb3RvdHlwZSwge1xuICAgICAgICBbU1RSRUFNX05BTUVfU1lNQk9MXToge1xuICAgICAgICAgIHZhbHVlOiB2YWx1ZS5uYW1lLFxuICAgICAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0sXG4gIH07XG59XG5cbi8qKlxuICogUmV2aXZlcnMgZm9yIGRlc2VyaWFsaXphdGlvbiBib3VuZGFyeSBmcm9tIHdpdGhpbiB0aGUgc3RlcCBleGVjdXRpb25cbiAqIGVudmlyb25tZW50LCByZWNlaXZpbmcgYXJndW1lbnRzIGZyb20gdGhlIHdvcmtmbG93IGhhbmRsZXIuXG4gKlxuICogQHBhcmFtIGdsb2JhbFxuICogQHBhcmFtIG9wc1xuICogQHBhcmFtIHJ1bklkXG4gKiBAcmV0dXJuc1xuICovXG5mdW5jdGlvbiBnZXRTdGVwUmV2aXZlcnMoXG4gIGdsb2JhbDogUmVjb3JkPHN0cmluZywgYW55PiA9IGdsb2JhbFRoaXMsXG4gIG9wczogUHJvbWlzZTx2b2lkPltdLFxuICBydW5JZDogc3RyaW5nLFxuICBjcnlwdG9LZXk6IEVuY3J5cHRpb25LZXlQYXJhbVxuKTogUmV2aXZlcnMge1xuICByZXR1cm4ge1xuICAgIC4uLmdldENvbW1vblJldml2ZXJzKGdsb2JhbCksXG5cbiAgICAvLyBTdGVwRnVuY3Rpb24gcmV2aXZlciBmb3Igc3RlcCBjb250ZXh0IC0gcmV0dXJucyByYXcgc3RlcCBmdW5jdGlvblxuICAgIC8vIHdpdGggY2xvc3VyZSB2YXJpYWJsZSBzdXBwb3J0IHZpYSBBc3luY0xvY2FsU3RvcmFnZVxuICAgIFN0ZXBGdW5jdGlvbjogKHZhbHVlKSA9PiB7XG4gICAgICBjb25zdCBzdGVwSWQgPSB2YWx1ZS5zdGVwSWQ7XG4gICAgICBjb25zdCBjbG9zdXJlVmFycyA9IHZhbHVlLmNsb3N1cmVWYXJzO1xuXG4gICAgICBjb25zdCBzdGVwRm4gPSBnZXRTdGVwRnVuY3Rpb24oc3RlcElkKTtcbiAgICAgIGlmICghc3RlcEZuKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgU3RlcCBmdW5jdGlvbiBcIiR7c3RlcElkfVwiIG5vdCBmb3VuZC4gTWFrZSBzdXJlIHRoZSBzdGVwIGZ1bmN0aW9uIGlzIHJlZ2lzdGVyZWQuYFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICAvLyBJZiBjbG9zdXJlIHZhcmlhYmxlcyB3ZXJlIHNlcmlhbGl6ZWQsIHJldHVybiBhIHdyYXBwZXIgZnVuY3Rpb25cbiAgICAgIC8vIHRoYXQgc2V0cyB1cCBBc3luY0xvY2FsU3RvcmFnZSBjb250ZXh0IHdoZW4gaW52b2tlZFxuICAgICAgaWYgKGNsb3N1cmVWYXJzKSB7XG4gICAgICAgIGNvbnN0IHdyYXBwZWRTdGVwRm4gPSAoKC4uLmFyZ3M6IGFueVtdKSA9PiB7XG4gICAgICAgICAgLy8gR2V0IHRoZSBjdXJyZW50IGNvbnRleHQgZnJvbSBBc3luY0xvY2FsU3RvcmFnZVxuICAgICAgICAgIGNvbnN0IGN1cnJlbnRDb250ZXh0ID0gY29udGV4dFN0b3JhZ2UuZ2V0U3RvcmUoKTtcblxuICAgICAgICAgIGlmICghY3VycmVudENvbnRleHQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgJ0Nhbm5vdCBjYWxsIHN0ZXAgZnVuY3Rpb24gd2l0aCBjbG9zdXJlIHZhcmlhYmxlcyBvdXRzaWRlIHN0ZXAgY29udGV4dCdcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gQ3JlYXRlIGEgbmV3IGNvbnRleHQgd2l0aCB0aGUgY2xvc3VyZSB2YXJpYWJsZXMgbWVyZ2VkIGluXG4gICAgICAgICAgY29uc3QgbmV3Q29udGV4dCA9IHtcbiAgICAgICAgICAgIC4uLmN1cnJlbnRDb250ZXh0LFxuICAgICAgICAgICAgY2xvc3VyZVZhcnMsXG4gICAgICAgICAgfTtcblxuICAgICAgICAgIC8vIFJ1biB0aGUgc3RlcCBmdW5jdGlvbiB3aXRoIHRoZSBuZXcgY29udGV4dCB0aGF0IGluY2x1ZGVzIGNsb3N1cmUgdmFyc1xuICAgICAgICAgIHJldHVybiBjb250ZXh0U3RvcmFnZS5ydW4obmV3Q29udGV4dCwgKCkgPT4gc3RlcEZuKC4uLmFyZ3MpKTtcbiAgICAgICAgfSkgYXMgYW55O1xuXG4gICAgICAgIC8vIENvcHkgcHJvcGVydGllcyBmcm9tIG9yaWdpbmFsIHN0ZXAgZnVuY3Rpb25cbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHdyYXBwZWRTdGVwRm4sICduYW1lJywge1xuICAgICAgICAgIHZhbHVlOiBzdGVwRm4ubmFtZSxcbiAgICAgICAgfSk7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh3cmFwcGVkU3RlcEZuLCAnc3RlcElkJywge1xuICAgICAgICAgIHZhbHVlOiBzdGVwSWQsXG4gICAgICAgICAgd3JpdGFibGU6IGZhbHNlLFxuICAgICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgICAgIGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoc3RlcEZuLm1heFJldHJpZXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHdyYXBwZWRTdGVwRm4ubWF4UmV0cmllcyA9IHN0ZXBGbi5tYXhSZXRyaWVzO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHdyYXBwZWRTdGVwRm47XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzdGVwRm47XG4gICAgfSxcblxuICAgIFdvcmtmbG93RnVuY3Rpb246ICh2YWx1ZSkgPT5cbiAgICAgIE9iamVjdC5hc3NpZ24oXG4gICAgICAgICgpID0+IHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAnV29ya2Zsb3cgZnVuY3Rpb25zIGNhbm5vdCBiZSBjYWxsZWQgZGlyZWN0bHkuIFVzZSBzdGFydCgpIHRvIGludm9rZSB0aGVtLidcbiAgICAgICAgICApO1xuICAgICAgICB9LFxuICAgICAgICB7IHdvcmtmbG93SWQ6IHZhbHVlLndvcmtmbG93SWQgfVxuICAgICAgKSxcblxuICAgIFJlcXVlc3Q6ICh2YWx1ZSkgPT4ge1xuICAgICAgY29uc3QgcmVzcG9uc2VXcml0YWJsZSA9IHZhbHVlLnJlc3BvbnNlV3JpdGFibGU7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gbmV3IGdsb2JhbC5SZXF1ZXN0KHZhbHVlLnVybCwge1xuICAgICAgICBtZXRob2Q6IHZhbHVlLm1ldGhvZCxcbiAgICAgICAgaGVhZGVyczogbmV3IGdsb2JhbC5IZWFkZXJzKHZhbHVlLmhlYWRlcnMpLFxuICAgICAgICBib2R5OiB2YWx1ZS5ib2R5LFxuICAgICAgICBkdXBsZXg6IHZhbHVlLmR1cGxleCxcbiAgICAgIH0pO1xuICAgICAgaWYgKHJlc3BvbnNlV3JpdGFibGUpIHtcbiAgICAgICAgcmVxdWVzdC5yZXNwb25kV2l0aCA9IGFzeW5jIChyZXNwb25zZTogUmVzcG9uc2UpID0+IHtcbiAgICAgICAgICBjb25zdCB3cml0ZXIgPSByZXNwb25zZVdyaXRhYmxlLmdldFdyaXRlcigpO1xuICAgICAgICAgIGF3YWl0IHdyaXRlci53cml0ZShyZXNwb25zZSk7XG4gICAgICAgICAgYXdhaXQgd3JpdGVyLmNsb3NlKCk7XG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVxdWVzdDtcbiAgICB9LFxuICAgIFJlc3BvbnNlOiAodmFsdWUpID0+IHtcbiAgICAgIC8vIE5vdGU6IFJlc3BvbnNlIGNvbnN0cnVjdG9yIG9ubHkgYWNjZXB0cyBzdGF0dXMsIHN0YXR1c1RleHQsIGFuZCBoZWFkZXJzXG4gICAgICAvLyBUaGUgdHlwZSwgdXJsLCBhbmQgcmVkaXJlY3RlZCBwcm9wZXJ0aWVzIGFyZSByZWFkLW9ubHkgYW5kIHNldCBieSB0aGUgY29uc3RydWN0b3JcbiAgICAgIHJldHVybiBuZXcgZ2xvYmFsLlJlc3BvbnNlKHZhbHVlLmJvZHksIHtcbiAgICAgICAgc3RhdHVzOiB2YWx1ZS5zdGF0dXMsXG4gICAgICAgIHN0YXR1c1RleHQ6IHZhbHVlLnN0YXR1c1RleHQsXG4gICAgICAgIGhlYWRlcnM6IG5ldyBnbG9iYWwuSGVhZGVycyh2YWx1ZS5oZWFkZXJzKSxcbiAgICAgIH0pO1xuICAgIH0sXG4gICAgUmVhZGFibGVTdHJlYW06ICh2YWx1ZSkgPT4ge1xuICAgICAgLy8gSWYgdGhpcyBoYXMgYm9keUluaXQsIGl0IGNhbWUgZnJvbSBhIFJlc3BvbnNlIGNvbnN0cnVjdG9yXG4gICAgICAvLyBDb252ZXJ0IGl0IHRvIGEgUkVBTCBzdHJlYW0gbm93IHRoYXQgd2UncmUgaW4gdGhlIHN0ZXAgZW52aXJvbm1lbnRcbiAgICAgIGlmICgnYm9keUluaXQnIGluIHZhbHVlKSB7XG4gICAgICAgIGNvbnN0IGJvZHlJbml0ID0gdmFsdWUuYm9keUluaXQ7XG4gICAgICAgIC8vIFVzZSB0aGUgbmF0aXZlIFJlc3BvbnNlIGNvbnN0cnVjdG9yIHRvIHByb3Blcmx5IGNvbnZlcnQgQm9keUluaXQgdG8gUmVhZGFibGVTdHJlYW1cbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBuZXcgZ2xvYmFsLlJlc3BvbnNlKGJvZHlJbml0KTtcbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmJvZHk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJlYWRhYmxlID0gbmV3IFdvcmtmbG93U2VydmVyUmVhZGFibGVTdHJlYW0ocnVuSWQsIHZhbHVlLm5hbWUpO1xuICAgICAgaWYgKHZhbHVlLnR5cGUgPT09ICdieXRlcycpIHtcbiAgICAgICAgLy8gRm9yIGJ5dGUgc3RyZWFtcywgdXNlIGZsdXNoYWJsZSBwaXBlIHdpdGggbG9jayBwb2xsaW5nXG4gICAgICAgIGNvbnN0IHN0YXRlID0gY3JlYXRlRmx1c2hhYmxlU3RhdGUoKTtcbiAgICAgICAgb3BzLnB1c2goc3RhdGUucHJvbWlzZSk7XG5cbiAgICAgICAgLy8gQ3JlYXRlIGFuIGlkZW50aXR5IHRyYW5zZm9ybSB0byBnaXZlIHRoZSB1c2VyIGEgcmVhZGFibGVcbiAgICAgICAgY29uc3QgeyByZWFkYWJsZTogdXNlclJlYWRhYmxlLCB3cml0YWJsZSB9ID1cbiAgICAgICAgICBuZXcgZ2xvYmFsLlRyYW5zZm9ybVN0cmVhbSgpO1xuXG4gICAgICAgIC8vIFN0YXJ0IHRoZSBmbHVzaGFibGUgcGlwZSBpbiB0aGUgYmFja2dyb3VuZFxuICAgICAgICBmbHVzaGFibGVQaXBlKHJlYWRhYmxlLCB3cml0YWJsZSwgc3RhdGUpLmNhdGNoKCgpID0+IHtcbiAgICAgICAgICAvLyBFcnJvcnMgYXJlIGhhbmRsZWQgdmlhIHN0YXRlLnJlamVjdFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBTdGFydCBwb2xsaW5nIHRvIGRldGVjdCB3aGVuIHVzZXIgcmVsZWFzZXMgbG9ja1xuICAgICAgICBwb2xsUmVhZGFibGVMb2NrKHVzZXJSZWFkYWJsZSwgc3RhdGUpO1xuXG4gICAgICAgIHJldHVybiB1c2VyUmVhZGFibGU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCB0cmFuc2Zvcm0gPSBnZXREZXNlcmlhbGl6ZVN0cmVhbShcbiAgICAgICAgICBnZXRTdGVwUmV2aXZlcnMoZ2xvYmFsLCBvcHMsIHJ1bklkLCBjcnlwdG9LZXkpLFxuICAgICAgICAgIGNyeXB0b0tleVxuICAgICAgICApO1xuICAgICAgICBjb25zdCBzdGF0ZSA9IGNyZWF0ZUZsdXNoYWJsZVN0YXRlKCk7XG4gICAgICAgIG9wcy5wdXNoKHN0YXRlLnByb21pc2UpO1xuXG4gICAgICAgIC8vIFN0YXJ0IHRoZSBmbHVzaGFibGUgcGlwZSBpbiB0aGUgYmFja2dyb3VuZFxuICAgICAgICBmbHVzaGFibGVQaXBlKHJlYWRhYmxlLCB0cmFuc2Zvcm0ud3JpdGFibGUsIHN0YXRlKS5jYXRjaCgoKSA9PiB7XG4gICAgICAgICAgLy8gRXJyb3JzIGFyZSBoYW5kbGVkIHZpYSBzdGF0ZS5yZWplY3RcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gU3RhcnQgcG9sbGluZyB0byBkZXRlY3Qgd2hlbiB1c2VyIHJlbGVhc2VzIGxvY2tcbiAgICAgICAgcG9sbFJlYWRhYmxlTG9jayh0cmFuc2Zvcm0ucmVhZGFibGUsIHN0YXRlKTtcblxuICAgICAgICByZXR1cm4gdHJhbnNmb3JtLnJlYWRhYmxlO1xuICAgICAgfVxuICAgIH0sXG4gICAgV3JpdGFibGVTdHJlYW06ICh2YWx1ZSkgPT4ge1xuICAgICAgY29uc3Qgc2VyaWFsaXplID0gZ2V0U2VyaWFsaXplU3RyZWFtKFxuICAgICAgICBnZXRTdGVwUmVkdWNlcnMoZ2xvYmFsLCBvcHMsIHJ1bklkLCBjcnlwdG9LZXkpLFxuICAgICAgICBjcnlwdG9LZXlcbiAgICAgICk7XG4gICAgICBjb25zdCBzZXJ2ZXJXcml0YWJsZSA9IG5ldyBXb3JrZmxvd1NlcnZlcldyaXRhYmxlU3RyZWFtKFxuICAgICAgICBydW5JZCxcbiAgICAgICAgdmFsdWUubmFtZVxuICAgICAgKTtcblxuICAgICAgLy8gQ3JlYXRlIGZsdXNoYWJsZSBzdGF0ZSBmb3IgdGhpcyBzdHJlYW1cbiAgICAgIGNvbnN0IHN0YXRlID0gY3JlYXRlRmx1c2hhYmxlU3RhdGUoKTtcbiAgICAgIG9wcy5wdXNoKHN0YXRlLnByb21pc2UpO1xuXG4gICAgICAvLyBTdGFydCB0aGUgZmx1c2hhYmxlIHBpcGUgaW4gdGhlIGJhY2tncm91bmRcbiAgICAgIGZsdXNoYWJsZVBpcGUoc2VyaWFsaXplLnJlYWRhYmxlLCBzZXJ2ZXJXcml0YWJsZSwgc3RhdGUpLmNhdGNoKCgpID0+IHtcbiAgICAgICAgLy8gRXJyb3JzIGFyZSBoYW5kbGVkIHZpYSBzdGF0ZS5yZWplY3RcbiAgICAgIH0pO1xuXG4gICAgICAvLyBTdGFydCBwb2xsaW5nIHRvIGRldGVjdCB3aGVuIHVzZXIgcmVsZWFzZXMgbG9ja1xuICAgICAgcG9sbFdyaXRhYmxlTG9jayhzZXJpYWxpemUud3JpdGFibGUsIHN0YXRlKTtcblxuICAgICAgcmV0dXJuIHNlcmlhbGl6ZS53cml0YWJsZTtcbiAgICB9LFxuICB9O1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBFbmNyeXB0aW9uIEhlbHBlcnNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBFbmNyeXB0IGRhdGEgaWYgdGhlIHdvcmxkIHN1cHBvcnRzIGVuY3J5cHRpb24uXG4gKiBSZXR1cm5zIG9yaWdpbmFsIGRhdGEgaWYgZW5jcnlwdGlvbiBpcyBub3QgYXZhaWxhYmxlLlxuICpcbiAqIEBwYXJhbSBkYXRhIC0gU2VyaWFsaXplZCBkYXRhIHRvIGVuY3J5cHRcbiAqIEBwYXJhbSBrZXkgLSBFbmNyeXB0aW9uIGtleSAodW5kZWZpbmVkIHRvIHNraXAgZW5jcnlwdGlvbilcbiAqIEBwYXJhbSBjb250ZXh0IC0gRW5jcnlwdGlvbiBjb250ZXh0IHdpdGggcnVuSWRcbiAqIEByZXR1cm5zIEVuY3J5cHRlZCBkYXRhIGlmIGVuY3J5cHRpb24gYXZhaWxhYmxlLCBvcmlnaW5hbCBkYXRhIG90aGVyd2lzZVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbWF5YmVFbmNyeXB0KFxuICBkYXRhOiBVaW50OEFycmF5LFxuICBrZXk6IENyeXB0b0tleSB8IHVuZGVmaW5lZFxuKTogUHJvbWlzZTxVaW50OEFycmF5PiB7XG4gIGlmICgha2V5KSByZXR1cm4gZGF0YTtcbiAgY29uc3QgZW5jcnlwdGVkID0gYXdhaXQgYWVzR2NtRW5jcnlwdChrZXksIGRhdGEpO1xuICByZXR1cm4gZW5jb2RlV2l0aEZvcm1hdFByZWZpeChcbiAgICBTZXJpYWxpemF0aW9uRm9ybWF0LkVOQ1JZUFRFRCxcbiAgICBlbmNyeXB0ZWRcbiAgKSBhcyBVaW50OEFycmF5O1xufVxuXG4vKipcbiAqIERlY3J5cHQgZGF0YSBpZiBpdCBoYXMgdGhlICdlbmNyJyBwcmVmaXguXG4gKlxuICogQHBhcmFtIGRhdGEgLSBEYXRhIHRoYXQgbWF5IGJlIGVuY3J5cHRlZFxuICogQHBhcmFtIGtleSAtIEVuY3J5cHRpb24ga2V5ICh1bmRlZmluZWQgaWYgbm8ga2V5IGF2YWlsYWJsZSlcbiAqIEByZXR1cm5zIERlY3J5cHRlZCBkYXRhIGlmIGVuY3J5cHRlZCwgb3JpZ2luYWwgZGF0YSBvdGhlcndpc2VcbiAqIEB0aHJvd3Mge1dvcmtmbG93UnVudGltZUVycm9yfSBJZiB0aGUgZGF0YSBpcyBlbmNyeXB0ZWQgYnV0IG5vIGtleSBpc1xuICogICBhdmFpbGFibGUuIENhbGxlcnMgKGUuZy4sIGBSdW4ucG9sbFJldHVyblZhbHVlKClgLCBgaHlkcmF0ZVN0ZXBSZXR1cm5WYWx1ZWApXG4gKiAgIHNob3VsZCBiZSBhd2FyZSB0aGlzIGNhbiBzdXJmYWNlIGFzIGEgcmVqZWN0ZWQgcHJvbWlzZSBkdXJpbmcga2V5IHJvdGF0aW9uXG4gKiAgIG9yIG1pc2NvbmZpZ3VyYXRpb24gc2NlbmFyaW9zLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbWF5YmVEZWNyeXB0KFxuICBkYXRhOiBVaW50OEFycmF5IHwgdW5rbm93bixcbiAga2V5OiBDcnlwdG9LZXkgfCB1bmRlZmluZWRcbik6IFByb21pc2U8VWludDhBcnJheSB8IHVua25vd24+IHtcbiAgLy8gTGVnYWN5IHNwZWNWZXJzaW9uIDEgcnVucyBzdG9yZWQgZXZlbnQgZGF0YSBhcyBwbGFpbiBKU09OIGFycmF5c1xuICAvLyAobm90IGJpbmFyeSBVaW50OEFycmF5KS4gUGFzcyB0aHJvdWdoIGFzLWlzIGZvciBiYWNrd2FyZHMgY29tcGF0LlxuICBpZiAoIShkYXRhIGluc3RhbmNlb2YgVWludDhBcnJheSkpIHtcbiAgICByZXR1cm4gZGF0YTtcbiAgfVxuXG4gIGlmIChpc0VuY3J5cHRlZChkYXRhKSkge1xuICAgIGlmICgha2V5KSB7XG4gICAgICB0aHJvdyBuZXcgV29ya2Zsb3dSdW50aW1lRXJyb3IoXG4gICAgICAgICdFbmNyeXB0ZWQgZGF0YSBlbmNvdW50ZXJlZCBidXQgbm8gZW5jcnlwdGlvbiBrZXkgaXMgYXZhaWxhYmxlLiAnICtcbiAgICAgICAgICAnRW5jcnlwdGlvbiBpcyBub3QgY29uZmlndXJlZCBvciBubyBrZXkgd2FzIHByb3ZpZGVkIGZvciB0aGlzIHJ1bi4nXG4gICAgICApO1xuICAgIH1cbiAgICAvLyBTdHJpcCB0aGUgJ2VuY3InIGZvcm1hdCBwcmVmaXgg4oCUIHRoZSBwcmVmaXggaXMgYSBjb3JlIGZyYW1pbmcgY29uY2VyblxuICAgIGNvbnN0IHsgcGF5bG9hZCB9ID0gZGVjb2RlRm9ybWF0UHJlZml4KGRhdGEpO1xuICAgIHJldHVybiBhZXNHY21EZWNyeXB0KGtleSwgcGF5bG9hZCk7XG4gIH1cblxuICByZXR1cm4gZGF0YTtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gRGVoeWRyYXRlIC8gSHlkcmF0ZSBGdW5jdGlvbnNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBDYWxsZWQgZnJvbSB0aGUgYHN0YXJ0KClgIGZ1bmN0aW9uIHRvIHNlcmlhbGl6ZSB0aGUgd29ya2Zsb3cgYXJndW1lbnRzXG4gKiBpbnRvIGEgZm9ybWF0IHRoYXQgY2FuIGJlIHNhdmVkIHRvIHRoZSBkYXRhYmFzZSBhbmQgdGhlbiBoeWRyYXRlZCBmcm9tXG4gKiB3aXRoaW4gdGhlIHdvcmtmbG93IGV4ZWN1dGlvbiBlbnZpcm9ubWVudC5cbiAqXG4gKiBAcGFyYW0gdmFsdWUgLSBUaGUgdmFsdWUgdG8gc2VyaWFsaXplXG4gKiBAcGFyYW0gcnVuSWQgLSBUaGUgd29ya2Zsb3cgcnVuIElEIChyZXF1aXJlZCBmb3IgZW5jcnlwdGlvbiBjb250ZXh0KVxuICogQHBhcmFtIGtleSAtIEVuY3J5cHRpb24ga2V5ICh1bmRlZmluZWQgdG8gc2tpcCBlbmNyeXB0aW9uKVxuICogQHBhcmFtIG9wcyAtIFByb21pc2UgYXJyYXkgZm9yIHN0cmVhbSBvcGVyYXRpb25zXG4gKiBAcGFyYW0gZ2xvYmFsIC0gR2xvYmFsIG9iamVjdCBmb3Igc2VyaWFsaXphdGlvbiBjb250ZXh0XG4gKiBAcGFyYW0gdjFDb21wYXQgLSBFbmFibGUgbGVnYWN5IHYxIGNvbXBhdGliaWxpdHkgbW9kZVxuICogQHJldHVybnMgVGhlIGRlaHlkcmF0ZWQgdmFsdWUgYXMgYmluYXJ5IGRhdGEgKFVpbnQ4QXJyYXkpIHdpdGggZm9ybWF0IHByZWZpeFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZGVoeWRyYXRlV29ya2Zsb3dBcmd1bWVudHMoXG4gIHZhbHVlOiB1bmtub3duLFxuICBydW5JZDogc3RyaW5nLFxuICBrZXk6IENyeXB0b0tleSB8IHVuZGVmaW5lZCxcbiAgb3BzOiBQcm9taXNlPHZvaWQ+W10gPSBbXSxcbiAgZ2xvYmFsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0gZ2xvYmFsVGhpcyxcbiAgdjFDb21wYXQgPSBmYWxzZVxuKTogUHJvbWlzZTxVaW50OEFycmF5IHwgdW5rbm93bj4ge1xuICB0cnkge1xuICAgIGNvbnN0IHN0ciA9IHN0cmluZ2lmeSh2YWx1ZSwgZ2V0RXh0ZXJuYWxSZWR1Y2VycyhnbG9iYWwsIG9wcywgcnVuSWQsIGtleSkpO1xuICAgIGlmICh2MUNvbXBhdCkge1xuICAgICAgcmV0dXJuIHJldml2ZShzdHIpO1xuICAgIH1cbiAgICBjb25zdCBwYXlsb2FkID0gbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKHN0cik7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IGVuY29kZVdpdGhGb3JtYXRQcmVmaXgoXG4gICAgICBTZXJpYWxpemF0aW9uRm9ybWF0LkRFVkFMVUVfVjEsXG4gICAgICBwYXlsb2FkXG4gICAgKSBhcyBVaW50OEFycmF5O1xuXG4gICAgLy8gRW5jcnlwdCBpZiB3b3JsZCBzdXBwb3J0cyBlbmNyeXB0aW9uXG4gICAgcmV0dXJuIG1heWJlRW5jcnlwdChzZXJpYWxpemVkLCBrZXkpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIHRocm93IG5ldyBXb3JrZmxvd1J1bnRpbWVFcnJvcihcbiAgICAgIGZvcm1hdFNlcmlhbGl6YXRpb25FcnJvcignd29ya2Zsb3cgYXJndW1lbnRzJywgZXJyb3IpLFxuICAgICAgeyBzbHVnOiAnc2VyaWFsaXphdGlvbi1mYWlsZWQnLCBjYXVzZTogZXJyb3IgfVxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBDYWxsZWQgZnJvbSB3b3JrZmxvdyBleGVjdXRpb24gZW52aXJvbm1lbnQgdG8gaHlkcmF0ZSB0aGUgd29ya2Zsb3dcbiAqIGFyZ3VtZW50cyBmcm9tIHRoZSBkYXRhYmFzZSBhdCB0aGUgc3RhcnQgb2Ygd29ya2Zsb3cgZXhlY3V0aW9uLlxuICpcbiAqIEBwYXJhbSB2YWx1ZSAtIEJpbmFyeSBzZXJpYWxpemVkIGRhdGEgKFVpbnQ4QXJyYXkpIHdpdGggZm9ybWF0IHByZWZpeFxuICogQHBhcmFtIF9ydW5JZCAtIFdvcmtmbG93IHJ1biBJRCAocmVzZXJ2ZWQgZm9yIGZ1dHVyZSBkZWNyeXB0aW9uIGNvbnRleHQ7IGRlY3J5cHRpb24gaXMgY3VycmVudGx5IGRyaXZlbiBzb2xlbHkgYnkgdGhlIHByb3ZpZGVkIGtleSlcbiAqIEBwYXJhbSBrZXkgLSBFbmNyeXB0aW9uIGtleSAodW5kZWZpbmVkIHRvIHNraXAgZGVjcnlwdGlvbilcbiAqIEBwYXJhbSBnbG9iYWwgLSBHbG9iYWwgb2JqZWN0IGZvciBkZXNlcmlhbGl6YXRpb24gY29udGV4dFxuICogQHBhcmFtIGV4dHJhUmV2aXZlcnMgLSBBZGRpdGlvbmFsIHJldml2ZXJzIGZvciBjdXN0b20gdHlwZXNcbiAqIEByZXR1cm5zIFRoZSBoeWRyYXRlZCB2YWx1ZVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaHlkcmF0ZVdvcmtmbG93QXJndW1lbnRzKFxuICB2YWx1ZTogVWludDhBcnJheSB8IHVua25vd24sXG4gIF9ydW5JZDogc3RyaW5nLFxuICBrZXk6IENyeXB0b0tleSB8IHVuZGVmaW5lZCxcbiAgZ2xvYmFsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0gZ2xvYmFsVGhpcyxcbiAgZXh0cmFSZXZpdmVyczogUmVjb3JkPHN0cmluZywgKHZhbHVlOiBhbnkpID0+IGFueT4gPSB7fVxuKSB7XG4gIC8vIERlY3J5cHQgaWYgbmVlZGVkXG4gIGNvbnN0IGRlY3J5cHRlZCA9IGF3YWl0IG1heWJlRGVjcnlwdCh2YWx1ZSwga2V5KTtcblxuICAvLyBMZWdhY3kgc3BlY1ZlcnNpb24gMSBydW5zIHN0b3JlZCBkYXRhIGFzIHBsYWluIEpTT04gYXJyYXlzIChub3QgYmluYXJ5KS5cbiAgLy8gVGhlc2UgcGFzcyB0aHJvdWdoIG1heWJlRGVjcnlwdCB1bmNoYW5nZWQgYW5kIGFyZSBkZXNlcmlhbGl6ZWQgZGlyZWN0bHlcbiAgLy8gdmlhIGRldmFsdWUncyB1bmZsYXR0ZW4oKS5cbiAgaWYgKCEoZGVjcnlwdGVkIGluc3RhbmNlb2YgVWludDhBcnJheSkpIHtcbiAgICByZXR1cm4gdW5mbGF0dGVuKGRlY3J5cHRlZCBhcyBhbnlbXSwge1xuICAgICAgLi4uZ2V0V29ya2Zsb3dSZXZpdmVycyhnbG9iYWwpLFxuICAgICAgLi4uZXh0cmFSZXZpdmVycyxcbiAgICB9KTtcbiAgfVxuXG4gIGNvbnN0IHsgZm9ybWF0LCBwYXlsb2FkIH0gPSBkZWNvZGVGb3JtYXRQcmVmaXgoZGVjcnlwdGVkKTtcblxuICBpZiAoZm9ybWF0ID09PSBTZXJpYWxpemF0aW9uRm9ybWF0LkRFVkFMVUVfVjEpIHtcbiAgICBjb25zdCBzdHIgPSBuZXcgVGV4dERlY29kZXIoKS5kZWNvZGUocGF5bG9hZCk7XG4gICAgY29uc3Qgb2JqID0gcGFyc2Uoc3RyLCB7XG4gICAgICAuLi5nZXRXb3JrZmxvd1Jldml2ZXJzKGdsb2JhbCksXG4gICAgICAuLi5leHRyYVJldml2ZXJzLFxuICAgIH0pO1xuICAgIHJldHVybiBvYmo7XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIHNlcmlhbGl6YXRpb24gZm9ybWF0OiAke2Zvcm1hdH1gKTtcbn1cblxuLyoqXG4gKiBEZWh5ZHJhdGUgd29ya2Zsb3cgcmV0dXJuIHZhbHVlIGZvciBzdG9yYWdlLlxuICpcbiAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSB0byBzZXJpYWxpemVcbiAqIEBwYXJhbSBydW5JZCAtIFJ1biBJRCBmb3IgZW5jcnlwdGlvbiBjb250ZXh0XG4gKiBAcGFyYW0ga2V5IC0gRW5jcnlwdGlvbiBrZXkgKHVuZGVmaW5lZCB0byBza2lwIGVuY3J5cHRpb24pXG4gKiBAcGFyYW0gZ2xvYmFsIC0gR2xvYmFsIG9iamVjdCBmb3Igc2VyaWFsaXphdGlvbiBjb250ZXh0XG4gKiBAcmV0dXJucyBUaGUgZGVoeWRyYXRlZCB2YWx1ZSBhcyBiaW5hcnkgZGF0YSAoVWludDhBcnJheSkgd2l0aCBmb3JtYXQgcHJlZml4XG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkZWh5ZHJhdGVXb3JrZmxvd1JldHVyblZhbHVlKFxuICB2YWx1ZTogdW5rbm93bixcbiAgX3J1bklkOiBzdHJpbmcsXG4gIGtleTogQ3J5cHRvS2V5IHwgdW5kZWZpbmVkLFxuICBnbG9iYWw6IFJlY29yZDxzdHJpbmcsIGFueT4gPSBnbG9iYWxUaGlzLFxuICB2MUNvbXBhdCA9IGZhbHNlXG4pOiBQcm9taXNlPFVpbnQ4QXJyYXkgfCB1bmtub3duPiB7XG4gIHRyeSB7XG4gICAgY29uc3Qgc3RyID0gc3RyaW5naWZ5KHZhbHVlLCBnZXRXb3JrZmxvd1JlZHVjZXJzKGdsb2JhbCkpO1xuICAgIGlmICh2MUNvbXBhdCkge1xuICAgICAgcmV0dXJuIHJldml2ZShzdHIpO1xuICAgIH1cbiAgICBjb25zdCBwYXlsb2FkID0gbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKHN0cik7XG4gICAgY29uc3Qgc2VyaWFsaXplZCA9IGVuY29kZVdpdGhGb3JtYXRQcmVmaXgoXG4gICAgICBTZXJpYWxpemF0aW9uRm9ybWF0LkRFVkFMVUVfVjEsXG4gICAgICBwYXlsb2FkXG4gICAgKSBhcyBVaW50OEFycmF5O1xuXG4gICAgLy8gRW5jcnlwdCBpZiB3b3JsZCBzdXBwb3J0cyBlbmNyeXB0aW9uXG4gICAgcmV0dXJuIG1heWJlRW5jcnlwdChzZXJpYWxpemVkLCBrZXkpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIHRocm93IG5ldyBXb3JrZmxvd1J1bnRpbWVFcnJvcihcbiAgICAgIGZvcm1hdFNlcmlhbGl6YXRpb25FcnJvcignd29ya2Zsb3cgcmV0dXJuIHZhbHVlJywgZXJyb3IpLFxuICAgICAgeyBzbHVnOiAnc2VyaWFsaXphdGlvbi1mYWlsZWQnLCBjYXVzZTogZXJyb3IgfVxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBDYWxsZWQgZnJvbSB0aGUgY2xpZW50IHNpZGUgKGkuZS4gdGhlIGV4ZWN1dGlvbiBlbnZpcm9ubWVudCB3aGVyZVxuICogdGhlIHdvcmtmbG93IHJ1biB3YXMgaW5pdGlhdGVkIGZyb20pIHRvIGh5ZHJhdGUgdGhlIHdvcmtmbG93XG4gKiByZXR1cm4gdmFsdWUgb2YgYSBjb21wbGV0ZWQgd29ya2Zsb3cgcnVuLlxuICpcbiAqIEBwYXJhbSB2YWx1ZSAtIEJpbmFyeSBzZXJpYWxpemVkIGRhdGEgKFVpbnQ4QXJyYXkpIHdpdGggZm9ybWF0IHByZWZpeFxuICogQHBhcmFtIHJ1bklkIC0gUnVuIElEIGZvciBkZWNyeXB0aW9uIGNvbnRleHRcbiAqIEBwYXJhbSBrZXkgLSBFbmNyeXB0aW9uIGtleSAodW5kZWZpbmVkIHRvIHNraXAgZGVjcnlwdGlvbilcbiAqIEBwYXJhbSBvcHMgLSBQcm9taXNlIGFycmF5IGZvciBzdHJlYW0gb3BlcmF0aW9uc1xuICogQHBhcmFtIGdsb2JhbCAtIEdsb2JhbCBvYmplY3QgZm9yIGRlc2VyaWFsaXphdGlvbiBjb250ZXh0XG4gKiBAcGFyYW0gZXh0cmFSZXZpdmVycyAtIEFkZGl0aW9uYWwgcmV2aXZlcnMgZm9yIGN1c3RvbSB0eXBlc1xuICogQHJldHVybnMgVGhlIGh5ZHJhdGVkIHJldHVybiB2YWx1ZSwgcmVhZHkgdG8gYmUgY29uc3VtZWQgYnkgdGhlIGNsaWVudFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaHlkcmF0ZVdvcmtmbG93UmV0dXJuVmFsdWUoXG4gIHZhbHVlOiBVaW50OEFycmF5IHwgdW5rbm93bixcbiAgcnVuSWQ6IHN0cmluZyxcbiAga2V5OiBDcnlwdG9LZXkgfCB1bmRlZmluZWQsXG4gIG9wczogUHJvbWlzZTx2b2lkPltdID0gW10sXG4gIGdsb2JhbDogUmVjb3JkPHN0cmluZywgYW55PiA9IGdsb2JhbFRoaXMsXG4gIGV4dHJhUmV2aXZlcnM6IFJlY29yZDxzdHJpbmcsICh2YWx1ZTogYW55KSA9PiBhbnk+ID0ge31cbikge1xuICAvLyBEZWNyeXB0IGlmIG5lZWRlZFxuICBjb25zdCBkZWNyeXB0ZWQgPSBhd2FpdCBtYXliZURlY3J5cHQodmFsdWUsIGtleSk7XG5cbiAgLy8gTGVnYWN5IHNwZWNWZXJzaW9uIDEgcnVucyBzdG9yZWQgZGF0YSBhcyBwbGFpbiBKU09OIGFycmF5cyAobm90IGJpbmFyeSkuXG4gIC8vIFRoZXNlIHBhc3MgdGhyb3VnaCBtYXliZURlY3J5cHQgdW5jaGFuZ2VkIGFuZCBhcmUgZGVzZXJpYWxpemVkIGRpcmVjdGx5XG4gIC8vIHZpYSBkZXZhbHVlJ3MgdW5mbGF0dGVuKCkuXG4gIGlmICghKGRlY3J5cHRlZCBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpKSB7XG4gICAgcmV0dXJuIHVuZmxhdHRlbihkZWNyeXB0ZWQgYXMgYW55W10sIHtcbiAgICAgIC4uLmdldEV4dGVybmFsUmV2aXZlcnMoZ2xvYmFsLCBvcHMsIHJ1bklkLCBrZXkpLFxuICAgICAgLi4uZXh0cmFSZXZpdmVycyxcbiAgICB9KTtcbiAgfVxuXG4gIGNvbnN0IHsgZm9ybWF0LCBwYXlsb2FkIH0gPSBkZWNvZGVGb3JtYXRQcmVmaXgoZGVjcnlwdGVkKTtcblxuICBpZiAoZm9ybWF0ID09PSBTZXJpYWxpemF0aW9uRm9ybWF0LkRFVkFMVUVfVjEpIHtcbiAgICBjb25zdCBzdHIgPSBuZXcgVGV4dERlY29kZXIoKS5kZWNvZGUocGF5bG9hZCk7XG4gICAgY29uc3Qgb2JqID0gcGFyc2Uoc3RyLCB7XG4gICAgICAuLi5nZXRFeHRlcm5hbFJldml2ZXJzKGdsb2JhbCwgb3BzLCBydW5JZCwga2V5KSxcbiAgICAgIC4uLmV4dHJhUmV2aXZlcnMsXG4gICAgfSk7XG4gICAgcmV0dXJuIG9iajtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgc2VyaWFsaXphdGlvbiBmb3JtYXQ6ICR7Zm9ybWF0fWApO1xufVxuXG4vKipcbiAqIENhbGxlZCBmcm9tIHRoZSB3b3JrZmxvdyBoYW5kbGVyIHdoZW4gYSBzdGVwIGlzIGJlaW5nIGNyZWF0ZWQuXG4gKiBEZWh5ZHJhdGVzIHZhbHVlcyBmcm9tIHdpdGhpbiB0aGUgd29ya2Zsb3cgZXhlY3V0aW9uIGVudmlyb25tZW50XG4gKiBpbnRvIGEgZm9ybWF0IHRoYXQgY2FuIGJlIHNhdmVkIHRvIHRoZSBkYXRhYmFzZS5cbiAqXG4gKiBAcGFyYW0gdmFsdWUgLSBUaGUgdmFsdWUgdG8gc2VyaWFsaXplXG4gKiBAcGFyYW0gcnVuSWQgLSBSdW4gSUQgZm9yIGVuY3J5cHRpb24gY29udGV4dFxuICogQHBhcmFtIGtleSAtIEVuY3J5cHRpb24ga2V5ICh1bmRlZmluZWQgdG8gc2tpcCBlbmNyeXB0aW9uKVxuICogQHBhcmFtIGdsb2JhbCAtIEdsb2JhbCBvYmplY3QgZm9yIHNlcmlhbGl6YXRpb24gY29udGV4dFxuICogQHBhcmFtIHYxQ29tcGF0IC0gRW5hYmxlIGxlZ2FjeSB2MSBjb21wYXRpYmlsaXR5IG1vZGVcbiAqIEByZXR1cm5zIFRoZSBkZWh5ZHJhdGVkIHZhbHVlIGFzIGJpbmFyeSBkYXRhIChVaW50OEFycmF5KSB3aXRoIGZvcm1hdCBwcmVmaXhcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlaHlkcmF0ZVN0ZXBBcmd1bWVudHMoXG4gIHZhbHVlOiB1bmtub3duLFxuICBfcnVuSWQ6IHN0cmluZyxcbiAga2V5OiBDcnlwdG9LZXkgfCB1bmRlZmluZWQsXG4gIGdsb2JhbDogUmVjb3JkPHN0cmluZywgYW55PiA9IGdsb2JhbFRoaXMsXG4gIHYxQ29tcGF0ID0gZmFsc2Vcbik6IFByb21pc2U8VWludDhBcnJheSB8IHVua25vd24+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCBzdHIgPSBzdHJpbmdpZnkodmFsdWUsIGdldFdvcmtmbG93UmVkdWNlcnMoZ2xvYmFsKSk7XG4gICAgaWYgKHYxQ29tcGF0KSB7XG4gICAgICByZXR1cm4gcmV2aXZlKHN0cik7XG4gICAgfVxuICAgIGNvbnN0IHBheWxvYWQgPSBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUoc3RyKTtcbiAgICBjb25zdCBzZXJpYWxpemVkID0gZW5jb2RlV2l0aEZvcm1hdFByZWZpeChcbiAgICAgIFNlcmlhbGl6YXRpb25Gb3JtYXQuREVWQUxVRV9WMSxcbiAgICAgIHBheWxvYWRcbiAgICApIGFzIFVpbnQ4QXJyYXk7XG5cbiAgICAvLyBFbmNyeXB0IGlmIHdvcmxkIHN1cHBvcnRzIGVuY3J5cHRpb25cbiAgICByZXR1cm4gbWF5YmVFbmNyeXB0KHNlcmlhbGl6ZWQsIGtleSk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgdGhyb3cgbmV3IFdvcmtmbG93UnVudGltZUVycm9yKFxuICAgICAgZm9ybWF0U2VyaWFsaXphdGlvbkVycm9yKCdzdGVwIGFyZ3VtZW50cycsIGVycm9yKSxcbiAgICAgIHsgc2x1ZzogJ3NlcmlhbGl6YXRpb24tZmFpbGVkJywgY2F1c2U6IGVycm9yIH1cbiAgICApO1xuICB9XG59XG5cbi8qKlxuICogQ2FsbGVkIGZyb20gdGhlIHN0ZXAgaGFuZGxlciB0byBoeWRyYXRlIHRoZSBhcmd1bWVudHMgb2YgYSBzdGVwXG4gKiBmcm9tIHRoZSBkYXRhYmFzZSBhdCB0aGUgc3RhcnQgb2YgdGhlIHN0ZXAgZXhlY3V0aW9uLlxuICpcbiAqIEBwYXJhbSB2YWx1ZSAtIEJpbmFyeSBzZXJpYWxpemVkIGRhdGEgKFVpbnQ4QXJyYXkpIHdpdGggZm9ybWF0IHByZWZpeFxuICogQHBhcmFtIHJ1bklkIC0gUnVuIElEIGZvciBkZWNyeXB0aW9uIGNvbnRleHRcbiAqIEBwYXJhbSBrZXkgLSBFbmNyeXB0aW9uIGtleSAodW5kZWZpbmVkIHRvIHNraXAgZGVjcnlwdGlvbilcbiAqIEBwYXJhbSBvcHMgLSBQcm9taXNlIGFycmF5IGZvciBzdHJlYW0gb3BlcmF0aW9uc1xuICogQHBhcmFtIGdsb2JhbCAtIEdsb2JhbCBvYmplY3QgZm9yIGRlc2VyaWFsaXphdGlvbiBjb250ZXh0XG4gKiBAcGFyYW0gZXh0cmFSZXZpdmVycyAtIEFkZGl0aW9uYWwgcmV2aXZlcnMgZm9yIGN1c3RvbSB0eXBlc1xuICogQHJldHVybnMgVGhlIGh5ZHJhdGVkIHZhbHVlLCByZWFkeSB0byBiZSBjb25zdW1lZCBieSB0aGUgc3RlcCB1c2VyLWNvZGUgZnVuY3Rpb25cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGh5ZHJhdGVTdGVwQXJndW1lbnRzKFxuICB2YWx1ZTogVWludDhBcnJheSB8IHVua25vd24sXG4gIHJ1bklkOiBzdHJpbmcsXG4gIGtleTogQ3J5cHRvS2V5IHwgdW5kZWZpbmVkLFxuICBvcHM6IFByb21pc2U8YW55PltdID0gW10sXG4gIGdsb2JhbDogUmVjb3JkPHN0cmluZywgYW55PiA9IGdsb2JhbFRoaXMsXG4gIGV4dHJhUmV2aXZlcnM6IFJlY29yZDxzdHJpbmcsICh2YWx1ZTogYW55KSA9PiBhbnk+ID0ge31cbikge1xuICAvLyBEZWNyeXB0IGlmIG5lZWRlZFxuICBjb25zdCBkZWNyeXB0ZWQgPSBhd2FpdCBtYXliZURlY3J5cHQodmFsdWUsIGtleSk7XG5cbiAgLy8gTGVnYWN5IHNwZWNWZXJzaW9uIDEgcnVucyBzdG9yZWQgZGF0YSBhcyBwbGFpbiBKU09OIGFycmF5cyAobm90IGJpbmFyeSkuXG4gIC8vIFRoZXNlIHBhc3MgdGhyb3VnaCBtYXliZURlY3J5cHQgdW5jaGFuZ2VkIGFuZCBhcmUgZGVzZXJpYWxpemVkIGRpcmVjdGx5XG4gIC8vIHZpYSBkZXZhbHVlJ3MgdW5mbGF0dGVuKCkuXG4gIGlmICghKGRlY3J5cHRlZCBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpKSB7XG4gICAgcmV0dXJuIHVuZmxhdHRlbihkZWNyeXB0ZWQgYXMgYW55W10sIHtcbiAgICAgIC4uLmdldFN0ZXBSZXZpdmVycyhnbG9iYWwsIG9wcywgcnVuSWQsIGtleSksXG4gICAgICAuLi5leHRyYVJldml2ZXJzLFxuICAgIH0pO1xuICB9XG5cbiAgY29uc3QgeyBmb3JtYXQsIHBheWxvYWQgfSA9IGRlY29kZUZvcm1hdFByZWZpeChkZWNyeXB0ZWQpO1xuXG4gIGlmIChmb3JtYXQgPT09IFNlcmlhbGl6YXRpb25Gb3JtYXQuREVWQUxVRV9WMSkge1xuICAgIGNvbnN0IHN0ciA9IG5ldyBUZXh0RGVjb2RlcigpLmRlY29kZShwYXlsb2FkKTtcbiAgICBjb25zdCBvYmogPSBwYXJzZShzdHIsIHtcbiAgICAgIC4uLmdldFN0ZXBSZXZpdmVycyhnbG9iYWwsIG9wcywgcnVuSWQsIGtleSksXG4gICAgICAuLi5leHRyYVJldml2ZXJzLFxuICAgIH0pO1xuICAgIHJldHVybiBvYmo7XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIHNlcmlhbGl6YXRpb24gZm9ybWF0OiAke2Zvcm1hdH1gKTtcbn1cblxuLyoqXG4gKiBDYWxsZWQgZnJvbSB0aGUgc3RlcCBoYW5kbGVyIHdoZW4gYSBzdGVwIGhhcyBjb21wbGV0ZWQuXG4gKiBEZWh5ZHJhdGVzIHZhbHVlcyBmcm9tIHdpdGhpbiB0aGUgc3RlcCBleGVjdXRpb24gZW52aXJvbm1lbnRcbiAqIGludG8gYSBmb3JtYXQgdGhhdCBjYW4gYmUgc2F2ZWQgdG8gdGhlIGRhdGFiYXNlLlxuICpcbiAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSB0byBzZXJpYWxpemVcbiAqIEBwYXJhbSBydW5JZCAtIFJ1biBJRCBmb3IgZW5jcnlwdGlvbiBjb250ZXh0XG4gKiBAcGFyYW0ga2V5IC0gRW5jcnlwdGlvbiBrZXkgKHVuZGVmaW5lZCB0byBza2lwIGVuY3J5cHRpb24pXG4gKiBAcGFyYW0gb3BzIC0gUHJvbWlzZSBhcnJheSBmb3Igc3RyZWFtIG9wZXJhdGlvbnNcbiAqIEBwYXJhbSBnbG9iYWwgLSBHbG9iYWwgb2JqZWN0IGZvciBzZXJpYWxpemF0aW9uIGNvbnRleHRcbiAqIEBwYXJhbSB2MUNvbXBhdCAtIEVuYWJsZSBsZWdhY3kgdjEgY29tcGF0aWJpbGl0eSBtb2RlXG4gKiBAcmV0dXJucyBUaGUgZGVoeWRyYXRlZCB2YWx1ZSBhcyBiaW5hcnkgZGF0YSAoVWludDhBcnJheSkgd2l0aCBmb3JtYXQgcHJlZml4XG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkZWh5ZHJhdGVTdGVwUmV0dXJuVmFsdWUoXG4gIHZhbHVlOiB1bmtub3duLFxuICBydW5JZDogc3RyaW5nLFxuICBrZXk6IENyeXB0b0tleSB8IHVuZGVmaW5lZCxcbiAgb3BzOiBQcm9taXNlPGFueT5bXSA9IFtdLFxuICBnbG9iYWw6IFJlY29yZDxzdHJpbmcsIGFueT4gPSBnbG9iYWxUaGlzLFxuICB2MUNvbXBhdCA9IGZhbHNlXG4pOiBQcm9taXNlPFVpbnQ4QXJyYXkgfCB1bmtub3duPiB7XG4gIHRyeSB7XG4gICAgY29uc3Qgc3RyID0gc3RyaW5naWZ5KHZhbHVlLCBnZXRTdGVwUmVkdWNlcnMoZ2xvYmFsLCBvcHMsIHJ1bklkLCBrZXkpKTtcbiAgICBpZiAodjFDb21wYXQpIHtcbiAgICAgIHJldHVybiByZXZpdmUoc3RyKTtcbiAgICB9XG4gICAgY29uc3QgcGF5bG9hZCA9IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShzdHIpO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSBlbmNvZGVXaXRoRm9ybWF0UHJlZml4KFxuICAgICAgU2VyaWFsaXphdGlvbkZvcm1hdC5ERVZBTFVFX1YxLFxuICAgICAgcGF5bG9hZFxuICAgICkgYXMgVWludDhBcnJheTtcblxuICAgIC8vIEVuY3J5cHQgaWYgd29ybGQgc3VwcG9ydHMgZW5jcnlwdGlvblxuICAgIHJldHVybiBtYXliZUVuY3J5cHQoc2VyaWFsaXplZCwga2V5KTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICB0aHJvdyBuZXcgV29ya2Zsb3dSdW50aW1lRXJyb3IoXG4gICAgICBmb3JtYXRTZXJpYWxpemF0aW9uRXJyb3IoJ3N0ZXAgcmV0dXJuIHZhbHVlJywgZXJyb3IpLFxuICAgICAgeyBzbHVnOiAnc2VyaWFsaXphdGlvbi1mYWlsZWQnLCBjYXVzZTogZXJyb3IgfVxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBDYWxsZWQgZnJvbSB0aGUgd29ya2Zsb3cgaGFuZGxlciB3aGVuIHJlcGxheWluZyB0aGUgZXZlbnQgbG9nIG9mIGEgYHN0ZXBfY29tcGxldGVkYCBldmVudC5cbiAqIEh5ZHJhdGVzIHRoZSByZXR1cm4gdmFsdWUgb2YgYSBzdGVwIGZyb20gdGhlIGRhdGFiYXNlLlxuICpcbiAqIEBwYXJhbSB2YWx1ZSAtIEJpbmFyeSBzZXJpYWxpemVkIGRhdGEgKFVpbnQ4QXJyYXkpIHdpdGggZm9ybWF0IHByZWZpeFxuICogQHBhcmFtIHJ1bklkIC0gUnVuIElEIGZvciBkZWNyeXB0aW9uIGNvbnRleHRcbiAqIEBwYXJhbSBrZXkgLSBFbmNyeXB0aW9uIGtleSAodW5kZWZpbmVkIHRvIHNraXAgZGVjcnlwdGlvbilcbiAqIEBwYXJhbSBnbG9iYWwgLSBHbG9iYWwgb2JqZWN0IGZvciBkZXNlcmlhbGl6YXRpb24gY29udGV4dFxuICogQHBhcmFtIGV4dHJhUmV2aXZlcnMgLSBBZGRpdGlvbmFsIHJldml2ZXJzIGZvciBjdXN0b20gdHlwZXNcbiAqIEByZXR1cm5zIFRoZSBoeWRyYXRlZCByZXR1cm4gdmFsdWUgb2YgYSBzdGVwLCByZWFkeSB0byBiZSBjb25zdW1lZCBieSB0aGUgd29ya2Zsb3cgaGFuZGxlclxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaHlkcmF0ZVN0ZXBSZXR1cm5WYWx1ZShcbiAgdmFsdWU6IFVpbnQ4QXJyYXkgfCB1bmtub3duLFxuICBfcnVuSWQ6IHN0cmluZyxcbiAga2V5OiBDcnlwdG9LZXkgfCB1bmRlZmluZWQsXG4gIGdsb2JhbDogUmVjb3JkPHN0cmluZywgYW55PiA9IGdsb2JhbFRoaXMsXG4gIGV4dHJhUmV2aXZlcnM6IFJlY29yZDxzdHJpbmcsICh2YWx1ZTogYW55KSA9PiBhbnk+ID0ge31cbikge1xuICAvLyBEZWNyeXB0IGlmIG5lZWRlZFxuICBjb25zdCBkZWNyeXB0ZWQgPSBhd2FpdCBtYXliZURlY3J5cHQodmFsdWUsIGtleSk7XG5cbiAgLy8gTGVnYWN5IHNwZWNWZXJzaW9uIDEgcnVucyBzdG9yZWQgZGF0YSBhcyBwbGFpbiBKU09OIGFycmF5cyAobm90IGJpbmFyeSkuXG4gIC8vIFRoZXNlIHBhc3MgdGhyb3VnaCBtYXliZURlY3J5cHQgdW5jaGFuZ2VkIGFuZCBhcmUgZGVzZXJpYWxpemVkIGRpcmVjdGx5XG4gIC8vIHZpYSBkZXZhbHVlJ3MgdW5mbGF0dGVuKCkuXG4gIGlmICghKGRlY3J5cHRlZCBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpKSB7XG4gICAgcmV0dXJuIHVuZmxhdHRlbihkZWNyeXB0ZWQgYXMgYW55W10sIHtcbiAgICAgIC4uLmdldFdvcmtmbG93UmV2aXZlcnMoZ2xvYmFsKSxcbiAgICAgIC4uLmV4dHJhUmV2aXZlcnMsXG4gICAgfSk7XG4gIH1cblxuICBjb25zdCB7IGZvcm1hdCwgcGF5bG9hZCB9ID0gZGVjb2RlRm9ybWF0UHJlZml4KGRlY3J5cHRlZCk7XG5cbiAgaWYgKGZvcm1hdCA9PT0gU2VyaWFsaXphdGlvbkZvcm1hdC5ERVZBTFVFX1YxKSB7XG4gICAgY29uc3Qgc3RyID0gbmV3IFRleHREZWNvZGVyKCkuZGVjb2RlKHBheWxvYWQpO1xuICAgIHJldHVybiBwYXJzZShzdHIsIHtcbiAgICAgIC4uLmdldFdvcmtmbG93UmV2aXZlcnMoZ2xvYmFsKSxcbiAgICAgIC4uLmV4dHJhUmV2aXZlcnMsXG4gICAgfSk7XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIHNlcmlhbGl6YXRpb24gZm9ybWF0OiAke2Zvcm1hdH1gKTtcbn1cbiJdfQ==
2272
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VyaWFsaXphdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9zZXJpYWxpemF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxzQkFBc0IsRUFDdEIsa0JBQWtCLEVBQ2xCLG9CQUFvQixHQUNyQixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUN0RCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDeEMsT0FBTyxFQUNMLE9BQU8sSUFBSSxhQUFhLEVBQ3hCLE9BQU8sSUFBSSxhQUFhLEVBRXhCLFNBQVMsR0FDVixNQUFNLGlCQUFpQixDQUFDO0FBQ3pCLE9BQU8sRUFDTCxvQkFBb0IsRUFDcEIsYUFBYSxFQUNiLGdCQUFnQixFQUNoQixnQkFBZ0IsR0FDakIsTUFBTSx1QkFBdUIsQ0FBQztBQUMvQixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQy9DLDJFQUEyRTtBQUMzRSwwRUFBMEU7QUFDMUUsMEVBQTBFO0FBQzFFLDREQUE0RDtBQUM1RCxzRUFBc0U7QUFDdEUsc0RBQXNEO0FBQ3RELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUMzRCxPQUFPLEtBQUssWUFBWSxNQUFNLDJCQUEyQixDQUFDO0FBQzFELE9BQU8sRUFFTCxRQUFRLEVBQ1IsVUFBVSxHQUNYLE1BQU0sZ0NBQWdDLENBQUM7QUFDeEMsT0FBTyxFQUNMLE9BQU8sRUFFUCxPQUFPLEVBQ1Asb0JBQW9CLEdBQ3JCLE1BQU0sK0JBQStCLENBQUM7QUFDdkMsT0FBTyxFQUNMLHdCQUF3QixFQUN4QixxQkFBcUIsR0FDdEIsTUFBTSwyQkFBMkIsQ0FBQztBQUNuQyxPQUFPLEVBQ0wsa0JBQWtCLEVBQ2xCLHNCQUFzQixFQUN0QixXQUFXLEVBQ1gsZ0JBQWdCLEdBQ2pC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bWVEZWNyeXB0aW9uRXJyb3IsXG4gIFNlcmlhbGl6YXRpb25FcnJvcixcbiAgV29ya2Zsb3dSdW50aW1lRXJyb3IsXG59IGZyb20gJ0B3b3JrZmxvdy9lcnJvcnMnO1xuaW1wb3J0IHsgcGFyc2UsIHN0cmluZ2lmeSwgdW5mbGF0dGVuIH0gZnJvbSAnZGV2YWx1ZSc7XG5pbXBvcnQgeyBtb25vdG9uaWNGYWN0b3J5IH0gZnJvbSAndWxpZCc7XG5pbXBvcnQge1xuICBkZWNyeXB0IGFzIGFlc0djbURlY3J5cHQsXG4gIGVuY3J5cHQgYXMgYWVzR2NtRW5jcnlwdCxcbiAgdHlwZSBDcnlwdG9LZXksXG4gIGltcG9ydEtleSxcbn0gZnJvbSAnLi9lbmNyeXB0aW9uLmpzJztcbmltcG9ydCB7XG4gIGNyZWF0ZUZsdXNoYWJsZVN0YXRlLFxuICBmbHVzaGFibGVQaXBlLFxuICBwb2xsUmVhZGFibGVMb2NrLFxuICBwb2xsV3JpdGFibGVMb2NrLFxufSBmcm9tICcuL2ZsdXNoYWJsZS1zdHJlYW0uanMnO1xuaW1wb3J0IHsgZ2V0U3RlcEZ1bmN0aW9uIH0gZnJvbSAnLi9wcml2YXRlLmpzJztcbi8vIFYyOiB1c2UgZ2V0V29ybGRMYXp5IGluIHN0ZXAtc2lkZSBjb2RlIHBhdGhzIHNvIFR1cmJvcGFjayBjYW4gc3RhdGljYWxseVxuLy8gcmVzb2x2ZSB0aGUgd29ybGQgYnJpZGdlIGZyb20gdGhlIHN0ZXAgYnVuZGxlIHdpdGhvdXQgZHJhZ2dpbmcgdGhlIGZ1bGxcbi8vIHdvcmxkLnRzIG1vZHVsZSAoYW5kIGl0cyBkeW5hbWljLWltcG9ydCBiZWhhdmlvdXIpIGludG8gdGhlIGZsb3cgcm91dGUuXG4vLyBTZWUgYHBhY2thZ2VzL2NvcmUvc3JjL3J1bnRpbWUvZ2V0LXdvcmxkLWxhenkudHNgIGFuZCB0aGVcbi8vIFwiVHVyYm9wYWNrIE5GVCBUcmFjaW5nIEVycm9ycyBpbiBWMiBDb21iaW5lZCBGbG93IFJvdXRlXCIgc2VjdGlvbiBvZlxuLy8gYGRvY3MvY29udGVudC9kb2NzL2NoYW5nZWxvZy9lYWdlci1wcm9jZXNzaW5nLm1keGAuXG5pbXBvcnQgeyBnZXRXb3JsZExhenkgfSBmcm9tICcuL3J1bnRpbWUvZ2V0LXdvcmxkLWxhenkuanMnO1xuaW1wb3J0ICogYXMgY2xpZW50TW9kdWxlIGZyb20gJy4vc2VyaWFsaXphdGlvbi9jbGllbnQuanMnO1xuaW1wb3J0IHtcbiAgdHlwZSBDb21wcmVzc2lvblN0YXRzLFxuICBjb21wcmVzcyxcbiAgZGVjb21wcmVzcyxcbn0gZnJvbSAnLi9zZXJpYWxpemF0aW9uL2NvbXByZXNzaW9uLmpzJztcbmltcG9ydCB7XG4gIGRlY3J5cHQsXG4gIHR5cGUgRW5jcnlwdGlvbktleVBhcmFtLFxuICBlbmNyeXB0LFxuICByZXNvbHZlRW5jcnlwdGlvbktleSxcbn0gZnJvbSAnLi9zZXJpYWxpemF0aW9uL2VuY3J5cHRpb24uanMnO1xuaW1wb3J0IHtcbiAgZm9ybWF0U2VyaWFsaXphdGlvbkVycm9yLFxuICByZXRocm93SWZSdW50aW1lRXJyb3IsXG59IGZyb20gJy4vc2VyaWFsaXphdGlvbi9lcnJvcnMuanMnO1xuaW1wb3J0IHtcbiAgZGVjb2RlRm9ybWF0UHJlZml4LFxuICBlbmNvZGVXaXRoRm9ybWF0UHJlZml4LFxuICBpc0VuY3J5cHRlZCxcbiAgcGVla0Zvcm1hdFByZWZpeCxcbn0gZnJvbSAnLi9zZXJpYWxpemF0aW9uL2Zvcm1hdC5qcyc7XG5pbXBvcnQge1xuICBnZXRDbGFzc1JlZHVjZXJzLFxuICBnZXRDbGFzc1Jldml2ZXJzLFxufSBmcm9tICcuL3NlcmlhbGl6YXRpb24vcmVkdWNlcnMvY2xhc3MuanMnO1xuaW1wb3J0IHtcbiAgZ2V0Q29tbW9uUmVkdWNlcnMsXG4gIGdldENvbW1vblJldml2ZXJzIGFzIGdldENvbW1vblJldml2ZXJzRnJvbU1vZHVsZSxcbiAgcmV2aXZlLFxufSBmcm9tICcuL3NlcmlhbGl6YXRpb24vcmVkdWNlcnMvY29tbW9uLmpzJztcbmltcG9ydCB7XG4gIGdldFN0ZXBGdW5jdGlvblJlZHVjZXIsXG4gIGdldFN0ZXBGdW5jdGlvblJldml2ZXIsXG59IGZyb20gJy4vc2VyaWFsaXphdGlvbi9yZWR1Y2Vycy9zdGVwLWZ1bmN0aW9uLmpzJztcbmltcG9ydCAqIGFzIHN0ZXBNb2R1bGUgZnJvbSAnLi9zZXJpYWxpemF0aW9uL3N0ZXAuanMnO1xuaW1wb3J0IHtcbiAgdHlwZSBGb3JtYXRQcmVmaXgsXG4gIGlzRm9ybWF0UHJlZml4LFxuICBTZXJpYWxpemF0aW9uRm9ybWF0LFxufSBmcm9tICcuL3NlcmlhbGl6YXRpb24vdHlwZXMuanMnO1xuaW1wb3J0ICogYXMgd29ya2Zsb3dNb2R1bGUgZnJvbSAnLi9zZXJpYWxpemF0aW9uL3dvcmtmbG93LmpzJztcbmltcG9ydCB7IGNvbnRleHRTdG9yYWdlIH0gZnJvbSAnLi9zdGVwL2NvbnRleHQtc3RvcmFnZS5qcyc7XG5pbXBvcnQge1xuICBBQk9SVF9IT09LX1RPS0VOLFxuICBBQk9SVF9MSVNURU5FUl9BVFRBQ0hFRCxcbiAgQUJPUlRfUkVBREVSX0NBTkNFTCxcbiAgQUJPUlRfU1RSRUFNX05BTUUsXG4gIEJPRFlfSU5JVF9TWU1CT0wsXG4gIFNUQUJMRV9VTElELFxuICBTVFJFQU1fRlJBTUlOR19TWU1CT0wsXG4gIFNUUkVBTV9OQU1FX1NZTUJPTCxcbiAgU1RSRUFNX1NFUlZFUl9ERVBMT1lNRU5UX0lEX1NZTUJPTCxcbiAgU1RSRUFNX1NFUlZFUl9SVU5fSURfU1lNQk9MLFxuICBTVFJFQU1fVFlQRV9TWU1CT0wsXG4gIFdFQkhPT0tfUkVTUE9OU0VfV1JJVEFCTEUsXG59IGZyb20gJy4vc3ltYm9scy5qcyc7XG5pbXBvcnQgKiBhcyBBdHRyIGZyb20gJy4vdGVsZW1ldHJ5L3NlbWFudGljLWNvbnZlbnRpb25zLmpzJztcbmltcG9ydCB7IGdldEFjdGl2ZVNwYW4gfSBmcm9tICcuL3RlbGVtZXRyeS5qcyc7XG5pbXBvcnQgeyBnZXRBYm9ydFN0cmVhbUlkIH0gZnJvbSAnLi91dGlsLmpzJztcbmltcG9ydCB7IFdvcmtmbG93QWJvcnRTaWduYWwgfSBmcm9tICcuL3dvcmtmbG93L2Fib3J0LWNvbnRyb2xsZXIuanMnO1xuXG4vLyBSZS1leHBvcnQgdHlwZXMgYW5kIHV0aWxpdGllcyBmcm9tIHRoZSBtb2R1bGFyIHNlcmlhbGl6YXRpb24gbW9kdWxlc1xuLy8gc28gZXhpc3RpbmcgY29uc3VtZXJzIG9mIGBAd29ya2Zsb3cvY29yZS9zZXJpYWxpemF0aW9uYCBrZWVwIHdvcmtpbmcuXG5leHBvcnQge1xuICBTZXJpYWxpemF0aW9uRm9ybWF0LFxuICB0eXBlIEZvcm1hdFByZWZpeCxcbiAgaXNGb3JtYXRQcmVmaXgsXG4gIGVuY29kZVdpdGhGb3JtYXRQcmVmaXgsXG4gIGRlY29kZUZvcm1hdFByZWZpeCxcbiAgcGVla0Zvcm1hdFByZWZpeCxcbiAgaXNFbmNyeXB0ZWQsXG4gIGVuY3J5cHQsXG4gIGRlY3J5cHQsXG4gIGNvbXByZXNzLFxuICBkZWNvbXByZXNzLFxuICB0eXBlIEVuY3J5cHRpb25LZXlQYXJhbSxcbn07XG5cbi8vIFJlLWV4cG9ydCB0aGUgbGVnYWN5IFNlcmlhbGl6YXRpb25Gb3JtYXRUeXBlIGZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eS5cbi8vIE5ldyBjb2RlIHNob3VsZCB1c2UgRm9ybWF0UHJlZml4IGZyb20gJy4vc2VyaWFsaXphdGlvbi90eXBlcy5qcycuXG5leHBvcnQgdHlwZSBTZXJpYWxpemF0aW9uRm9ybWF0VHlwZSA9XG4gICh0eXBlb2YgU2VyaWFsaXphdGlvbkZvcm1hdClba2V5b2YgdHlwZW9mIFNlcmlhbGl6YXRpb25Gb3JtYXRdO1xuXG4vKipcbiAqIERlZmF1bHQgVUxJRCBnZW5lcmF0b3IgZm9yIGNvbnRleHRzIHdoZXJlIFZNJ3Mgc2VlZGVkIGBzdGFibGVVbGlkYCBpc24ndCBhdmFpbGFibGUuXG4gKiBVc2VkIGFzIGEgZmFsbGJhY2sgd2hlbiBzZXJpYWxpemluZyBzdHJlYW1zIG91dHNpZGUgdGhlIHdvcmtmbG93IFZNIGNvbnRleHRcbiAqIChlLmcuLCB3aGVuIHN0YXJ0aW5nIGEgd29ya2Zsb3cgb3IgaGFuZGxpbmcgc3RlcCByZXR1cm4gdmFsdWVzKS5cbiAqL1xuY29uc3QgZGVmYXVsdFVsaWQgPSBtb25vdG9uaWNGYWN0b3J5KCk7XG5cbi8qKlxuICogRGV0ZWN0IGlmIGEgcmVhZGFibGUgc3RyZWFtIGlzIGEgYnl0ZSBzdHJlYW0uXG4gKlxuICogQHBhcmFtIHN0cmVhbVxuICogQHJldHVybnMgYFwiYnl0ZXNcImAgaWYgdGhlIHN0cmVhbSBpcyBhIGJ5dGUgc3RyZWFtLCBgdW5kZWZpbmVkYCBvdGhlcndpc2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFN0cmVhbVR5cGUoc3RyZWFtOiBSZWFkYWJsZVN0cmVhbSk6ICdieXRlcycgfCB1bmRlZmluZWQge1xuICB0cnkge1xuICAgIGNvbnN0IHJlYWRlciA9IHN0cmVhbS5nZXRSZWFkZXIoeyBtb2RlOiAnYnlvYicgfSk7XG4gICAgcmVhZGVyLnJlbGVhc2VMb2NrKCk7XG4gICAgcmV0dXJuICdieXRlcyc7XG4gIH0gY2F0Y2gge31cbn1cblxuLyoqXG4gKiBGcmFtZSBmb3JtYXQgZm9yIHN0cmVhbSBjaHVua3M6XG4gKiAgIFs0LWJ5dGUgYmlnLWVuZGlhbiBsZW5ndGhdW2Zvcm1hdC1wcmVmaXhlZCBwYXlsb2FkXVxuICpcbiAqIEVhY2ggY2h1bmsgaXMgaW5kZXBlbmRlbnRseSBmcmFtZWQgc28gdGhlIGRlc2VyaWFsaXplciBjYW4gZmluZFxuICogY2h1bmsgYm91bmRhcmllcyBldmVuIHdoZW4gbXVsdGlwbGUgY2h1bmtzIGFyZSBjb25jYXRlbmF0ZWQgb3JcbiAqIHNwbGl0IGFjcm9zcyB0cmFuc3BvcnQgcmVhZHMuXG4gKi9cbmNvbnN0IEZSQU1FX0hFQURFUl9TSVpFID0gNDtcblxuLyoqXG4gKiBUaGUgbW9kZS1zcGVjaWZpYyBzZXJpYWxpemVycyAoYC4vc2VyaWFsaXphdGlvbi97Y2xpZW50LHN0ZXAsd29ya2Zsb3d9LnRzYClcbiAqIGFscmVhZHkgdGhyb3cgYSBgU2VyaWFsaXphdGlvbkVycm9yYCB3aG9zZSBgLmNhdXNlYCBpcyB0aGUgdW5kZXJseWluZ1xuICogZGV2YWx1ZSAvIHNlcmRlIGZhaWx1cmUuIFRoZSBvdXRlciBkZWh5ZHJhdGUvaHlkcmF0ZSB3cmFwcGVycyB3YW50IHRvXG4gKiByZS1mcmFtZSB0aGF0IGVycm9yIHdpdGggYSBtb3JlIHNwZWNpZmljIGNvbnRleHQgbGFiZWwgKGUuZy4gXCJ3b3JrZmxvd1xuICogYXJndW1lbnRzXCIgaW5zdGVhZCBvZiBnZW5lcmljIFwid29ya2Zsb3cgdmFsdWVcIiksIHNvIHRoZXkgdW53cmFwIHRoZVxuICogaW5uZXIgU2VyaWFsaXphdGlvbkVycm9yIGFuZCByZWZvcm1hdCB3aXRoIHRoZSBvcmlnaW5hbCBjYXVzZS4gRXJyb3JzXG4gKiB0aGF0IGFyZW4ndCBhbHJlYWR5IFNlcmlhbGl6YXRpb25FcnJvciBmbG93IHRocm91Z2ggdW5jaGFuZ2VkLlxuICpcbiAqIGBSdW50aW1lRGVjcnlwdGlvbkVycm9yYCBpcyBhbiBleGNlcHRpb246IGl0IG11c3Qga2VlcCBpdHMgaWRlbnRpdHkgKGFuZFxuICogYGNvbnRleHRgKSBzbyB0aGUgcnVuLWZhaWx1cmUgY2xhc3NpZmllciByb3V0ZXMgaXQgdG8gYFJVTlRJTUVfRVJST1JgLFxuICogc28gdGhpcyByZXRocm93cyBpdCB1bmNoYW5nZWQgYmVmb3JlIGFueSB1bndyYXBwaW5nLiBOb3RlIHRoaXMgZ3VhcmRcbiAqIG11c3QgcnVuIGJlZm9yZSB0aGUgZ2VuZXJpYyBgV29ya2Zsb3dSdW50aW1lRXJyb3JgIHVud3JhcCBiZWxvdywgc2luY2VcbiAqIGBSdW50aW1lRGVjcnlwdGlvbkVycm9yYCBleHRlbmRzIGBXb3JrZmxvd1J1bnRpbWVFcnJvcmAgYW5kIGNhcnJpZXMgYVxuICogYGNhdXNlYCAodGhlIHVuZGVybHlpbmcgRE9NRXhjZXB0aW9uKSB0aGF0IHdvdWxkIG90aGVyd2lzZSBiZSB1bndyYXBwZWRcbiAqIGFuZCByZWZyYW1lZCBhcyBhIGBTZXJpYWxpemF0aW9uRXJyb3JgLlxuICovXG5mdW5jdGlvbiB1bndyYXBTZXJpYWxpemF0aW9uQ2F1c2UoZXJyb3I6IHVua25vd24pOiB1bmtub3duIHtcbiAgcmV0aHJvd0lmUnVudGltZUVycm9yKGVycm9yKTtcbiAgaWYgKGVycm9yIGluc3RhbmNlb2YgU2VyaWFsaXphdGlvbkVycm9yICYmIGVycm9yLmNhdXNlICE9PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gZXJyb3IuY2F1c2U7XG4gIH1cbiAgaWYgKGVycm9yIGluc3RhbmNlb2YgV29ya2Zsb3dSdW50aW1lRXJyb3IgJiYgZXJyb3IuY2F1c2UgIT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiBlcnJvci5jYXVzZTtcbiAgfVxuICByZXR1cm4gZXJyb3I7XG59XG5cbi8qKlxuICogRW1pdCBjb21wcmVzc2lvbiB0ZWxlbWV0cnkgb250byB0aGUgYWN0aXZlIHNwYW4gYWZ0ZXIgYSAoZGUpc2VyaWFsaXplLlxuICpcbiAqIFRoZSBjb21wcmVzc2lvbiBsYXllciBwb3B1bGF0ZXMgYHN0YXRzYCBvbmx5IHdoZW4gaXQgYWN0dWFsbHkgcmFuIChiaW5hcnlcbiAqIGRhdGEgb24gYSBzcGVjID49IDUgcGF0aCk7IGxlZ2FjeSAvIHYxQ29tcGF0IHBhdGhzIGxlYXZlIGl0IHVucmVjb3JkZWQsIHNvXG4gKiB0aGlzIG5vLW9wcyBmb3IgdGhlbSBhbmQgYXZvaWRzIHRoZSBgZ2V0QWN0aXZlU3BhbmAgbG9va3VwLiBBdHRyaWJ1dGVzIGxhbmRcbiAqIG9uIHdoYXRldmVyIHNwYW4gaXMgYWN0aXZlIOKAlCB0eXBpY2FsbHkgdGhlIGRlZGljYXRlZCBgc3RlcC5kZWh5ZHJhdGVgIC9cbiAqIGBzdGVwLmh5ZHJhdGVgIHNwYW4sIG90aGVyd2lzZSB0aGUgZW5jbG9zaW5nIHJ1bi9zdGFydCBzcGFuLlxuICovXG5hc3luYyBmdW5jdGlvbiByZWNvcmRDb21wcmVzc2lvbihcbiAgc3RhdHM6IENvbXByZXNzaW9uU3RhdHMsXG4gIG9wZXJhdGlvbjogJ3NlcmlhbGl6ZScgfCAnZGVzZXJpYWxpemUnXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgaWYgKCFzdGF0cy5yZWNvcmRlZCkgcmV0dXJuO1xuICAvLyBUZWxlbWV0cnkgbXVzdCBuZXZlciBicmVhayB0aGUgc2VyaWFsaXplL2Rlc2VyaWFsaXplIGRhdGEgcGF0aCDigJQgYVxuICAvLyBtaXNzaW5nL2ZhaWxpbmcgdHJhY2VyIGlzIHB1cmVseSBhbiBvYnNlcnZhYmlsaXR5IGxvc3MuXG4gIHRyeSB7XG4gICAgY29uc3Qgc3BhbiA9IGF3YWl0IGdldEFjdGl2ZVNwYW4oKTtcbiAgICBpZiAoIXNwYW4pIHJldHVybjtcbiAgICBjb25zdCB1bmNvbXByZXNzZWRCeXRlcyA9IHN0YXRzLnVuY29tcHJlc3NlZEJ5dGVzID8/IDA7XG4gICAgY29uc3Qgc3RvcmVkQnl0ZXMgPSBzdGF0cy5zdG9yZWRCeXRlcyA/PyAwO1xuICAgIHNwYW4uc2V0QXR0cmlidXRlcyh7XG4gICAgICAuLi5BdHRyLlNlcmlhbGl6YXRpb25PcGVyYXRpb24ob3BlcmF0aW9uKSxcbiAgICAgIC4uLkF0dHIuU2VyaWFsaXphdGlvbkNvbXByZXNzZWQoc3RhdHMuY29tcHJlc3NlZCA/PyBmYWxzZSksXG4gICAgICAuLi5BdHRyLlNlcmlhbGl6YXRpb25Db2RlYyhzdGF0cy5jb2RlYyA/PyAnbm9uZScpLFxuICAgICAgLi4uQXR0ci5TZXJpYWxpemF0aW9uVW5jb21wcmVzc2VkQnl0ZXModW5jb21wcmVzc2VkQnl0ZXMpLFxuICAgICAgLi4uQXR0ci5TZXJpYWxpemF0aW9uU3RvcmVkQnl0ZXMoc3RvcmVkQnl0ZXMpLFxuICAgICAgLi4uKHN0YXRzLmNvbXByZXNzZWQgJiYgdW5jb21wcmVzc2VkQnl0ZXMgPiAwXG4gICAgICAgID8gQXR0ci5TZXJpYWxpemF0aW9uQ29tcHJlc3Npb25SYXRpbyhcbiAgICAgICAgICAgIDEgLSBzdG9yZWRCeXRlcyAvIHVuY29tcHJlc3NlZEJ5dGVzXG4gICAgICAgICAgKVxuICAgICAgICA6IHt9KSxcbiAgICB9KTtcbiAgfSBjYXRjaCB7XG4gICAgLy8gaWdub3JlIHRlbGVtZXRyeSBmYWlsdXJlc1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTZXJpYWxpemVTdHJlYW0oXG4gIHJlZHVjZXJzOiBQYXJ0aWFsPFJlZHVjZXJzPixcbiAgY3J5cHRvS2V5OiBFbmNyeXB0aW9uS2V5UGFyYW1cbik6IFRyYW5zZm9ybVN0cmVhbTxhbnksIFVpbnQ4QXJyYXk+IHtcbiAgY29uc3QgZW5jb2RlciA9IG5ldyBUZXh0RW5jb2RlcigpO1xuICAvLyBSZXNvbHZlIHRoZSBrZXkgaW5wdXQgb25jZSBvbiBmaXJzdCB1c2UgYW5kIGNhY2hlIHRoZSByZXN1bHQuXG4gIC8vIE5vdGU6IGlmIHJlc29sdmluZyBjcnlwdG9LZXkgcmVqZWN0cyAoZS5nLiwgbmV0d29yayBlcnJvciBmZXRjaGluZ1xuICAvLyB0aGUgZGVyaXZlZCBrZXkpLCB0aGUgcmVqZWN0aW9uIHdvbid0IHN1cmZhY2UgdW50aWwgdGhlIGZpcnN0IGNodW5rXG4gIC8vIGlzIHByb2Nlc3NlZCDigJQgbm90IGF0IHN0cmVhbSBjb25zdHJ1Y3Rpb24gdGltZS5cbiAgY29uc3Qga2V5U3RhdGUgPSB7IHJlc29sdmVkOiBmYWxzZSwga2V5OiB1bmRlZmluZWQgYXMgQ3J5cHRvS2V5IHwgdW5kZWZpbmVkIH07XG4gIGNvbnN0IHN0cmVhbSA9IG5ldyBUcmFuc2Zvcm1TdHJlYW08YW55LCBVaW50OEFycmF5Pih7XG4gICAgYXN5bmMgdHJhbnNmb3JtKGNodW5rLCBjb250cm9sbGVyKSB7XG4gICAgICB0cnkge1xuICAgICAgICBpZiAoIWtleVN0YXRlLnJlc29sdmVkKSB7XG4gICAgICAgICAga2V5U3RhdGUua2V5ID0gYXdhaXQgcmVzb2x2ZUVuY3J5cHRpb25LZXkoY3J5cHRvS2V5KTtcbiAgICAgICAgICBrZXlTdGF0ZS5yZXNvbHZlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgc2VyaWFsaXplZCA9IHN0cmluZ2lmeShjaHVuaywgcmVkdWNlcnMpO1xuICAgICAgICBjb25zdCBwYXlsb2FkID0gZW5jb2Rlci5lbmNvZGUoc2VyaWFsaXplZCk7XG4gICAgICAgIGxldCBwcmVmaXhlZCA9IGVuY29kZVdpdGhGb3JtYXRQcmVmaXgoXG4gICAgICAgICAgU2VyaWFsaXphdGlvbkZvcm1hdC5ERVZBTFVFX1YxLFxuICAgICAgICAgIHBheWxvYWRcbiAgICAgICAgKSBhcyBVaW50OEFycmF5O1xuXG4gICAgICAgIC8vIEVuY3J5cHQgdGhlIGZyYW1lIHBheWxvYWQgaWYgYSBrZXkgaXMgcHJvdmlkZWQuXG4gICAgICAgIC8vIFRoZSBsZW5ndGggaGVhZGVyIHJlbWFpbnMgaW4gdGhlIGNsZWFyIHNvIHRoZSBkZXNlcmlhbGl6ZXIgY2FuXG4gICAgICAgIC8vIGZpbmQgZnJhbWUgYm91bmRhcmllcyByZWdhcmRsZXNzIG9mIHRyYW5zcG9ydCBjaHVua2luZy5cbiAgICAgICAgaWYgKGtleVN0YXRlLmtleSkge1xuICAgICAgICAgIGNvbnN0IGVuY3J5cHRlZCA9IGF3YWl0IGFlc0djbUVuY3J5cHQoa2V5U3RhdGUua2V5LCBwcmVmaXhlZCk7XG4gICAgICAgICAgcHJlZml4ZWQgPSBlbmNvZGVXaXRoRm9ybWF0UHJlZml4KFxuICAgICAgICAgICAgU2VyaWFsaXphdGlvbkZvcm1hdC5FTkNSWVBURUQsXG4gICAgICAgICAgICBlbmNyeXB0ZWRcbiAgICAgICAgICApIGFzIFVpbnQ4QXJyYXk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBXcml0ZSBsZW5ndGgtcHJlZml4ZWQgZnJhbWU6IFs0LWJ5dGUgbGVuZ3RoXVtwcmVmaXhlZCBkYXRhXVxuICAgICAgICBjb25zdCBmcmFtZSA9IG5ldyBVaW50OEFycmF5KEZSQU1FX0hFQURFUl9TSVpFICsgcHJlZml4ZWQubGVuZ3RoKTtcbiAgICAgICAgbmV3IERhdGFWaWV3KGZyYW1lLmJ1ZmZlcikuc2V0VWludDMyKDAsIHByZWZpeGVkLmxlbmd0aCwgZmFsc2UpO1xuICAgICAgICBmcmFtZS5zZXQocHJlZml4ZWQsIEZSQU1FX0hFQURFUl9TSVpFKTtcbiAgICAgICAgY29udHJvbGxlci5lbnF1ZXVlKGZyYW1lKTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIC8vIEVuY3J5cHRpb24gZmFpbHVyZXMgbXVzdCBrZWVwIHRoZWlyIFJ1bnRpbWVEZWNyeXB0aW9uRXJyb3JcbiAgICAgICAgLy8gaWRlbnRpdHkgKFJVTlRJTUVfRVJST1IpIHJhdGhlciB0aGFuIGJlIHJlZnJhbWVkIGFzIGFcbiAgICAgICAgLy8gU2VyaWFsaXphdGlvbkVycm9yIChVU0VSX0VSUk9SKS5cbiAgICAgICAgaWYgKFJ1bnRpbWVEZWNyeXB0aW9uRXJyb3IuaXMoZXJyb3IpKSB7XG4gICAgICAgICAgY29udHJvbGxlci5lcnJvcihlcnJvcik7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHsgbWVzc2FnZSwgaGludCB9ID0gZm9ybWF0U2VyaWFsaXphdGlvbkVycm9yKFxuICAgICAgICAgICdzdHJlYW0gY2h1bmsnLFxuICAgICAgICAgIGVycm9yXG4gICAgICAgICk7XG4gICAgICAgIGNvbnRyb2xsZXIuZXJyb3IoXG4gICAgICAgICAgbmV3IFNlcmlhbGl6YXRpb25FcnJvcihtZXNzYWdlLCB7IGhpbnQsIGNhdXNlOiBlcnJvciB9KVxuICAgICAgICApO1xuICAgICAgfVxuICAgIH0sXG4gIH0pO1xuICByZXR1cm4gc3RyZWFtO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RGVzZXJpYWxpemVTdHJlYW0oXG4gIHJldml2ZXJzOiBQYXJ0aWFsPFJldml2ZXJzPixcbiAgY3J5cHRvS2V5OiBFbmNyeXB0aW9uS2V5UGFyYW1cbik6IFRyYW5zZm9ybVN0cmVhbTxVaW50OEFycmF5LCBhbnk+IHtcbiAgY29uc3QgZGVjb2RlciA9IG5ldyBUZXh0RGVjb2RlcigpO1xuICBsZXQgYnVmZmVyID0gbmV3IFVpbnQ4QXJyYXkoMCk7XG4gIC8vIFJlc29sdmUgdGhlIGtleSBpbnB1dCBvbmNlIG9uIGZpcnN0IHVzZSBhbmQgY2FjaGUgdGhlIHJlc3VsdC5cbiAgY29uc3Qga2V5U3RhdGUgPSB7IHJlc29sdmVkOiBmYWxzZSwga2V5OiB1bmRlZmluZWQgYXMgQ3J5cHRvS2V5IHwgdW5kZWZpbmVkIH07XG5cbiAgZnVuY3Rpb24gYXBwZW5kVG9CdWZmZXIoZGF0YTogVWludDhBcnJheSkge1xuICAgIGNvbnN0IG5ld0J1ZmZlciA9IG5ldyBVaW50OEFycmF5KGJ1ZmZlci5sZW5ndGggKyBkYXRhLmxlbmd0aCk7XG4gICAgbmV3QnVmZmVyLnNldChidWZmZXIsIDApO1xuICAgIG5ld0J1ZmZlci5zZXQoZGF0YSwgYnVmZmVyLmxlbmd0aCk7XG4gICAgYnVmZmVyID0gbmV3QnVmZmVyO1xuICB9XG5cbiAgYXN5bmMgZnVuY3Rpb24gcHJvY2Vzc0ZyYW1lcyhcbiAgICBjb250cm9sbGVyOiBUcmFuc2Zvcm1TdHJlYW1EZWZhdWx0Q29udHJvbGxlcjxhbnk+XG4gICkge1xuICAgIC8vIFJlc29sdmUgdGhlIGtleSBpbnB1dCBvbmNlIG9uIGZpcnN0IHVzZSBhbmQgY2FjaGUgdGhlIHJlc3VsdFxuICAgIGlmICgha2V5U3RhdGUucmVzb2x2ZWQpIHtcbiAgICAgIGtleVN0YXRlLmtleSA9IGF3YWl0IHJlc29sdmVFbmNyeXB0aW9uS2V5KGNyeXB0b0tleSk7XG4gICAgICBrZXlTdGF0ZS5yZXNvbHZlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgLy8gVHJ5IHRvIGV4dHJhY3QgY29tcGxldGUgbGVuZ3RoLXByZWZpeGVkIGZyYW1lc1xuICAgIHdoaWxlIChidWZmZXIubGVuZ3RoID49IEZSQU1FX0hFQURFUl9TSVpFKSB7XG4gICAgICBjb25zdCBmcmFtZUxlbmd0aCA9IG5ldyBEYXRhVmlldyhcbiAgICAgICAgYnVmZmVyLmJ1ZmZlcixcbiAgICAgICAgYnVmZmVyLmJ5dGVPZmZzZXQsXG4gICAgICAgIGJ1ZmZlci5ieXRlTGVuZ3RoXG4gICAgICApLmdldFVpbnQzMigwLCBmYWxzZSk7XG5cbiAgICAgIGlmIChidWZmZXIubGVuZ3RoIDwgRlJBTUVfSEVBREVSX1NJWkUgKyBmcmFtZUxlbmd0aCkge1xuICAgICAgICBicmVhazsgLy8gSW5jb21wbGV0ZSBmcmFtZSwgd2FpdCBmb3IgbW9yZSBkYXRhXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGZyYW1lRGF0YSA9IGJ1ZmZlci5zbGljZShcbiAgICAgICAgRlJBTUVfSEVBREVSX1NJWkUsXG4gICAgICAgIEZSQU1FX0hFQURFUl9TSVpFICsgZnJhbWVMZW5ndGhcbiAgICAgICk7XG4gICAgICBidWZmZXIgPSBidWZmZXIuc2xpY2UoRlJBTUVfSEVBREVSX1NJWkUgKyBmcmFtZUxlbmd0aCk7XG5cbiAgICAgIGxldCB7IGZvcm1hdCwgcGF5bG9hZCB9ID0gZGVjb2RlRm9ybWF0UHJlZml4KGZyYW1lRGF0YSk7XG5cbiAgICAgIC8vIElmIHRoZSBmcmFtZSBwYXlsb2FkIGlzIGVuY3J5cHRlZCwgZGVjcnlwdCBpdCBmaXJzdCB0byByZXZlYWxcbiAgICAgIC8vIHRoZSBpbm5lciBmb3JtYXQtcHJlZml4ZWQgZGF0YSAoZS5nLiwgJ2RldmwnICsgc2VyaWFsaXplZCB0ZXh0KSxcbiAgICAgIC8vIHRoZW4gZmFsbCB0aHJvdWdoIHRvIHRoZSBub3JtYWwgZGVzZXJpYWxpemF0aW9uIHBhdGguXG4gICAgICBpZiAoZm9ybWF0ID09PSBTZXJpYWxpemF0aW9uRm9ybWF0LkVOQ1JZUFRFRCkge1xuICAgICAgICBpZiAoIWtleVN0YXRlLmtleSkge1xuICAgICAgICAgIGNvbnRyb2xsZXIuZXJyb3IoXG4gICAgICAgICAgICBuZXcgUnVudGltZURlY3J5cHRpb25FcnJvcihcbiAgICAgICAgICAgICAgJ0VuY3J5cHRlZCBzdHJlYW0gZGF0YSBlbmNvdW50ZXJlZCBidXQgbm8gZW5jcnlwdGlvbiBrZXkgaXMgYXZhaWxhYmxlLiAnICtcbiAgICAgICAgICAgICAgICAnRW5jcnlwdGlvbiBpcyBub3QgY29uZmlndXJlZCBvciBubyBrZXkgd2FzIHByb3ZpZGVkIGZvciB0aGlzIHJ1bi4nLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgY29udGV4dDoge1xuICAgICAgICAgICAgICAgICAgb3BlcmF0aW9uOiAnZGVjcnlwdCcsXG4gICAgICAgICAgICAgICAgICBieXRlTGVuZ3RoOiBwYXlsb2FkLmJ5dGVMZW5ndGgsXG4gICAgICAgICAgICAgICAgICBmb3JtYXRQcmVmaXg6ICdlbmNyJyxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApXG4gICAgICAgICAgKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGRlY3J5cHRlZDogVWludDhBcnJheTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBkZWNyeXB0ZWQgPSBhd2FpdCBhZXNHY21EZWNyeXB0KGtleVN0YXRlLmtleSwgcGF5bG9hZCk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgLy8gVGhlIGxvdy1sZXZlbCBBRVMgbGF5ZXIgb25seSBzZWVzIHRoZSBzdHJpcHBlZCBwYXlsb2FkLCBzbyBpdFxuICAgICAgICAgIC8vIGNhbm5vdCByZWNvcmQgdGhlIG91dGVyIGVudmVsb3BlIHByZWZpeC4gV2UgcGVla2VkIGl0IGhlcmVcbiAgICAgICAgICAvLyAoYGVuY3JgKSwgc28gZW5yaWNoIHRoZSBkaWFnbm9zdGljIGNvbnRleHQgd2l0aCB0aGUgcmVhbCBmb3JtYXRcbiAgICAgICAgICAvLyBwcmVmaXggYmVmb3JlIHByb3BhZ2F0aW5nIOKAlCBtaXJyb3Jpbmcgc2VyaWFsaXphdGlvbi9lbmNyeXB0aW9uLnRzLlxuICAgICAgICAgIGlmIChSdW50aW1lRGVjcnlwdGlvbkVycm9yLmlzKGVycm9yKSAmJiBlcnJvci5jb250ZXh0KSB7XG4gICAgICAgICAgICBlcnJvci5jb250ZXh0LmZvcm1hdFByZWZpeCA9IGZvcm1hdDtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICAgICAgKHsgZm9ybWF0LCBwYXlsb2FkIH0gPSBkZWNvZGVGb3JtYXRQcmVmaXgoZGVjcnlwdGVkKSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChmb3JtYXQgPT09IFNlcmlhbGl6YXRpb25Gb3JtYXQuREVWQUxVRV9WMSkge1xuICAgICAgICBjb25zdCB0ZXh0ID0gZGVjb2Rlci5kZWNvZGUocGF5bG9hZCk7XG4gICAgICAgIGNvbnRyb2xsZXIuZW5xdWV1ZShwYXJzZSh0ZXh0LCByZXZpdmVycykpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHN0cmVhbSA9IG5ldyBUcmFuc2Zvcm1TdHJlYW08VWludDhBcnJheSwgYW55Pih7XG4gICAgYXN5bmMgdHJhbnNmb3JtKGNodW5rLCBjb250cm9sbGVyKSB7XG4gICAgICAvLyBGaXJzdCwgdHJ5IHRvIGRldGVjdCBpZiB0aGlzIGlzIGxlbmd0aC1wcmVmaXhlZCBmcmFtZWQgZGF0YVxuICAgICAgLy8gYnkgY2hlY2tpbmcgaWYgdGhlIGZpcnN0IDQgYnl0ZXMgZm9ybSBhIHBsYXVzaWJsZSBsZW5ndGguXG4gICAgICBpZiAoYnVmZmVyLmxlbmd0aCA9PT0gMCAmJiBjaHVuay5sZW5ndGggPj0gRlJBTUVfSEVBREVSX1NJWkUpIHtcbiAgICAgICAgY29uc3QgcG9zc2libGVMZW5ndGggPSBuZXcgRGF0YVZpZXcoXG4gICAgICAgICAgY2h1bmsuYnVmZmVyLFxuICAgICAgICAgIGNodW5rLmJ5dGVPZmZzZXQsXG4gICAgICAgICAgY2h1bmsuYnl0ZUxlbmd0aFxuICAgICAgICApLmdldFVpbnQzMigwLCBmYWxzZSk7XG4gICAgICAgIGlmIChcbiAgICAgICAgICBwb3NzaWJsZUxlbmd0aCA+IDAgJiZcbiAgICAgICAgICBwb3NzaWJsZUxlbmd0aCA8IDEwMF8wMDBfMDAwIC8vIHNhbml0eSBjaGVjazogPCAxMDBNQlxuICAgICAgICApIHtcbiAgICAgICAgICAvLyBMb29rcyBsaWtlIGZyYW1lZCBkYXRhXG4gICAgICAgICAgYXBwZW5kVG9CdWZmZXIoY2h1bmspO1xuICAgICAgICAgIGF3YWl0IHByb2Nlc3NGcmFtZXMoY29udHJvbGxlcik7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGJ1ZmZlci5sZW5ndGggPiAwKSB7XG4gICAgICAgIC8vIEFscmVhZHkgaW4gZnJhbWVkIG1vZGUgKGhhdmUgYnVmZmVyZWQgZGF0YSlcbiAgICAgICAgYXBwZW5kVG9CdWZmZXIoY2h1bmspO1xuICAgICAgICBhd2FpdCBwcm9jZXNzRnJhbWVzKGNvbnRyb2xsZXIpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIC8vIExlZ2FjeSBmb3JtYXQ6IG5ld2xpbmUtZGVsaW1pdGVkIGRldmFsdWUgdGV4dCAobm8gZnJhbWluZylcbiAgICAgIGNvbnN0IHRleHQgPSBkZWNvZGVyLmRlY29kZShjaHVuayk7XG4gICAgICBjb25zdCBsaW5lcyA9IHRleHQuc3BsaXQoJ1xcbicpO1xuICAgICAgZm9yIChjb25zdCBsaW5lIG9mIGxpbmVzKSB7XG4gICAgICAgIGlmIChsaW5lLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBjb250cm9sbGVyLmVucXVldWUocGFyc2UobGluZSwgcmV2aXZlcnMpKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sXG4gICAgYXN5bmMgZmx1c2goY29udHJvbGxlcikge1xuICAgICAgLy8gUHJvY2VzcyBhbnkgcmVtYWluaW5nIGZyYW1lZCBkYXRhXG4gICAgICBpZiAoYnVmZmVyLmxlbmd0aCA+IDApIHtcbiAgICAgICAgYXdhaXQgcHJvY2Vzc0ZyYW1lcyhjb250cm9sbGVyKTtcbiAgICAgIH1cbiAgICB9LFxuICB9KTtcbiAgcmV0dXJuIHN0cmVhbTtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gQnl0ZS1zdHJlYW0gd2lyZSBmcmFtaW5nXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vL1xuLy8gQnl0ZSBzdHJlYW1zIChgdHlwZTogJ2J5dGVzJ2AgUmVhZGFibGVTdHJlYW1zIHBhc3NlZCBhY3Jvc3MgYm91bmRhcmllcylcbi8vIGFyZSB3cml0dGVuIHRvIHRoZSB1bmRlcmx5aW5nIHdvcmxkJ3Mgc3RyZWFtIHRyYW5zcG9ydCBvbmUgdXNlciBjaHVuayBhdFxuLy8gYSB0aW1lLiBXaXRob3V0IGFuIGluLWJhbmQgZW52ZWxvcGUsIHRoZSByZWFkZXIgc2VlcyBhIGZsYXQgc3RyZWFtIG9mXG4vLyBieXRlcyDigJQgdGhlcmUgaXMgbm8gd2F5IHRvIHRlbGwgd2hlcmUgb25lIHVzZXIgY2h1bmsgZW5kcyBhbmQgdGhlIG5leHRcbi8vIGJlZ2lucywgd2hpY2ggbWFrZXMgbWlkLXN0cmVhbSByZWNvbm5lY3QgaW1wb3NzaWJsZSAod2UgZG9uJ3Qga25vdyBob3dcbi8vIG1hbnkgc2VydmVyLXNpZGUgY2h1bmtzIGhhdmUgYmVlbiBjb25zdW1lZCkuXG4vL1xuLy8gVG8gZW5hYmxlIHRyYW5zcGFyZW50IHJlY29ubmVjdCwgdGhpcyBQUiBpbnRyb2R1Y2VzIGFuIG9wdC1pbiB3aXJlXG4vLyBlbnZlbG9wZSB0aGF0IHdyYXBzIGVhY2ggdXNlciBjaHVuayBpbiBhIGxlbmd0aC1wcmVmaXg6XG4vL1xuLy8gICBbNC1ieXRlIGJpZy1lbmRpYW4gbGVuZ3RoXVt1c2VyIHBheWxvYWQgYnl0ZXNdXG4vL1xuLy8gVGhlIGVudmVsb3BlIGlzIGlkZW50aWNhbCBpbiBzaGFwZSB0byBgZ2V0U2VyaWFsaXplU3RyZWFtYCdzIGZyYW1pbmcsXG4vLyBidXQgdGhlIHBheWxvYWQgaGVyZSBpcyAqcmF3IHVzZXIgYnl0ZXMqIOKAlCB0aGVyZSBpcyBubyBpbm5lclxuLy8gZm9ybWF0LXByZWZpeCwgbm8gZGV2YWx1ZSwgbm8gZW5jcnlwdGlvbi4gQSBmcmFtZWQgYnl0ZSBzdHJlYW0gc3RheXNcbi8vIHNlbWFudGljYWxseSBhIGJ5dGUgc3RyZWFtIGVuZC10by1lbmQ7IHRoZSBmcmFtaW5nIGlzIHB1cmVseSB0cmFuc3BvcnQuXG4vL1xuLy8gVGhlIGRlY2lzaW9uIHRvIHVzZSBmcmFtaW5nIGZvciBhIGdpdmVuIHN0cmVhbSBpcyByZWNvcmRlZCBpbiB0aGVcbi8vIHNlcmlhbGl6ZWQgc3RyZWFtIHJlZiAoYGZyYW1pbmc6ICdmcmFtZWQtdjEnYCksIHNvIGJvdGggc2lkZXMgYWdyZWUgb25cbi8vIHRoZSB3aXJlIGZvcm1hdCB3aXRob3V0IHJ1bnRpbWUgbmVnb3RpYXRpb24uIFByb2R1Y2VycyB0aGF0IHRhcmdldCBhXG4vLyBydW4gd2hvc2UgZGVwbG95bWVudCBkb2Vzbid0IHN1cHBvcnQgZnJhbWluZyAoc2VlIGBnZXRSdW5DYXBhYmlsaXRpZXNgXG4vLyBpbiBjYXBhYmlsaXRpZXMudHMpIGVtaXQgcmF3IGJ5dGVzIGFuZCBhIHJlZiB3aXRob3V0IHRoZSBmaWVsZCDigJQgd2hpY2hcbi8vIHRoZSByZWFkZXIgdHJlYXRzIGFzIGxlZ2FjeSByYXcgYnl0ZXMgZm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5LlxuXG4vKipcbiAqIE1heGltdW0gYWxsb3dlZCBieXRlLXN0cmVhbSBmcmFtZSBwYXlsb2FkIHNpemUgKDEwME1CKS4gU2hhcmVkIGJ5IHRoZVxuICogZnJhbWVyIChyZWplY3RzIG92ZXJzaXplZCB1c2VyIGNodW5rcyBhdCB3cml0ZSB0aW1lLCB3aGVyZSB0aGUgZXJyb3IgaXNcbiAqIGFjdGlvbmFibGUpIGFuZCB0aGUgdW5mcmFtZXIgKHJlamVjdHMgb3ZlcnNpemVkIGxlbmd0aCBoZWFkZXJzIGF0IHJlYWRcbiAqIHRpbWUsIHdoaWNoIHVzdWFsbHkgaW5kaWNhdGUgYSBub24tZnJhbWVkIHdpcmUgYmVpbmcgcmVhZCBhcyBmcmFtZWQpLlxuICogS2VlcGluZyBib3RoIHNpZGVzIG9uIG9uZSBjb25zdGFudCBndWFyYW50ZWVzIGFueSBjaHVuayB0aGUgZnJhbWVyXG4gKiBhY2NlcHRzIGNhbiBhbHdheXMgYmUgZGVjb2RlZCBieSB0aGUgdW5mcmFtZXIuXG4gKi9cbmNvbnN0IE1BWF9GUkFNRV9TSVpFID0gMTAwXzAwMF8wMDA7XG5cbi8qKlxuICogV3JhcHMgZWFjaCBjaHVuayBvZiBhIGJ5dGUgc3RyZWFtIGluIGEgNC1ieXRlIGJpZy1lbmRpYW4gbGVuZ3RoXG4gKiBwcmVmaXguIFVzZWQgYnkgdGhlIHByb2R1Y2VyIHNpZGUgb2YgYSBmcmFtZWQgYnl0ZS1zdHJlYW0gcGlwZS5cbiAqXG4gKiBFbXB0eSBjaHVua3MgKGxlbmd0aCAwKSBhcmUgZHJvcHBlZCDigJQgdGhlIHJlc3VsdGluZyBgWzB4MDAgMHgwMCAweDAwIDB4MDBdYFxuICogZnJhbWUgd291bGQgYmUgYW1iaWd1b3VzIHdpdGggdGhlIGxlZ2FjeSBcImxvb2tzIGZyYW1lZFwiIGRldGVjdGlvbiBpblxuICogYGdldERlc2VyaWFsaXplU3RyZWFtYCwgYW5kIGl0IGNhcnJpZXMgbm8gaW5mb3JtYXRpb24uXG4gKlxuICogTG9hZC1iZWFyaW5nIGludmFyaWFudDogZWFjaCB1c2VyIGNodW5rIGJlY29tZXMgZXhhY3RseSBvbmUgZnJhbWUsIGFuZFxuICogZWFjaCBmcmFtZSBpcyBlbnF1ZXVlZCBhcyBleGFjdGx5IG9uZSB0cmFuc3BvcnQgY2h1bmsgKHRoZSBkb3duc3RyZWFtXG4gKiB3cml0YWJsZSBwZXJmb3JtcyBvbmUgd2lyZSB3cml0ZSBwZXIgY2h1bmssIHByZXNlcnZpbmcgYm91bmRhcmllcykuIFRoZVxuICogc2VydmVyIHRoZXJlZm9yZSBzdG9yZXMgb25lIGZyYW1lIHBlciBjaHVuayBpbmRleCwgd2hpY2ggaXMgd2hhdCBhbGxvd3NcbiAqIGEgZnV0dXJlIHJlY29ubmVjdGluZyByZWFkZXIgdG8gcmVzdW1lIGEgZnJhbWVkIGJ5dGUgc3RyZWFtIGF0XG4gKiBgc3RhcnRJbmRleCArIGNvbnN1bWVkRnJhbWVzYCDigJQgdGhlIHNhbWUgYXJpdGhtZXRpY1xuICogYGNyZWF0ZVJlY29ubmVjdGluZ0ZyYW1lZFN0cmVhbWAgcmVsaWVzIG9uIGZvciBvYmplY3Qgc3RyZWFtcy4gRG8gbm90XG4gKiBjb2FsZXNjZSBvciBzcGxpdCBmcmFtZXMgaGVyZSB3aXRob3V0IHJldmlzaXRpbmcgdGhhdCByZXN1bWUgbG9naWMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRCeXRlRnJhbWluZ1N0cmVhbSgpOiBUcmFuc2Zvcm1TdHJlYW08XG4gIFVpbnQ4QXJyYXksXG4gIFVpbnQ4QXJyYXlcbj4ge1xuICByZXR1cm4gbmV3IFRyYW5zZm9ybVN0cmVhbTxVaW50OEFycmF5LCBVaW50OEFycmF5Pih7XG4gICAgdHJhbnNmb3JtKGNodW5rLCBjb250cm9sbGVyKSB7XG4gICAgICBpZiAoY2h1bmsubGVuZ3RoID09PSAwKSByZXR1cm47XG4gICAgICBpZiAoY2h1bmsubGVuZ3RoID4gTUFYX0ZSQU1FX1NJWkUpIHtcbiAgICAgICAgY29udHJvbGxlci5lcnJvcihcbiAgICAgICAgICBuZXcgV29ya2Zsb3dSdW50aW1lRXJyb3IoXG4gICAgICAgICAgICBgQnl0ZS1zdHJlYW0gY2h1bmsgb2YgJHtjaHVuay5sZW5ndGh9IGJ5dGVzIGV4Y2VlZHMgdGhlIG1heGltdW0gYCArXG4gICAgICAgICAgICAgIGBmcmFtZWQgY2h1bmsgc2l6ZSAoJHtNQVhfRlJBTUVfU0laRX0pLiBTcGxpdCB0aGUgZGF0YSBpbnRvIGAgK1xuICAgICAgICAgICAgICBgc21hbGxlciBjaHVua3MgYmVmb3JlIHdyaXRpbmcuYCxcbiAgICAgICAgICAgIHsgc2x1ZzogJ3NlcmlhbGl6YXRpb24tZmFpbGVkJyB9XG4gICAgICAgICAgKVxuICAgICAgICApO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBjb25zdCBmcmFtZSA9IG5ldyBVaW50OEFycmF5KEZSQU1FX0hFQURFUl9TSVpFICsgY2h1bmsubGVuZ3RoKTtcbiAgICAgIG5ldyBEYXRhVmlldyhmcmFtZS5idWZmZXIpLnNldFVpbnQzMigwLCBjaHVuay5sZW5ndGgsIGZhbHNlKTtcbiAgICAgIGZyYW1lLnNldChjaHVuaywgRlJBTUVfSEVBREVSX1NJWkUpO1xuICAgICAgY29udHJvbGxlci5lbnF1ZXVlKGZyYW1lKTtcbiAgICB9LFxuICB9KTtcbn1cblxuLyoqXG4gKiBVbndyYXBzIGxlbmd0aC1wcmVmaXhlZCBieXRlLXN0cmVhbSBmcmFtZXMgYmFjayBpbnRvIHRoZSBvcmlnaW5hbCB1c2VyXG4gKiBjaHVua3MuIFVzZWQgYnkgdGhlIGNvbnN1bWVyIHNpZGUgb2YgYSBmcmFtZWQgYnl0ZS1zdHJlYW0gcGlwZS5cbiAqXG4gKiBCdWZmZXJzIGFjcm9zcyByZWFkIGJvdW5kYXJpZXMg4oCUIHRoZSB0cmFuc3BvcnQgbWF5IHNwbGl0IGEgc2luZ2xlXG4gKiBmcmFtZSBhY3Jvc3MgbXVsdGlwbGUgcmVhZHMgKGhlYWRlciBpbiBvbmUgY2h1bmssIHBheWxvYWQgaW4gYW5vdGhlcilcbiAqIG9yIGNvYWxlc2NlIG11bHRpcGxlIGZyYW1lcyBpbnRvIGEgc2luZ2xlIHJlYWQuIFRoZSB0cmFuc2Zvcm0gZW1pdHNcbiAqIHdob2xlIHVzZXIgY2h1bmtzIHJlZ2FyZGxlc3Mgb2YgdHJhbnNwb3J0IGNodW5raW5nLlxuICpcbiAqIEVycm9ycyB0aGUgc3RyZWFtIGlmIHRoZSBsZW5ndGggaGVhZGVyIGFkdmVydGlzZXMgYSBmcmFtZSBsYXJnZXIgdGhhblxuICogYE1BWF9GUkFNRV9TSVpFYCBieXRlcywgc2luY2UgdGhhdCBhbG1vc3QgY2VydGFpbmx5IGluZGljYXRlcyBhXG4gKiBtaXNmcmFtZWQgd2lyZSAoZS5nLiBhIHJhdyBieXRlIHN0cmVhbSBiZWluZyBmZWQgdGhyb3VnaCB0aGlzIHRyYW5zZm9ybVxuICogYnkgbWlzdGFrZSkgYW5kIHdlIGRvbid0IHdhbnQgdG8gYWxsb2NhdGUgYW4gZW5vcm1vdXMgYnVmZmVyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0Qnl0ZVVuZnJhbWluZ1N0cmVhbSgpOiBUcmFuc2Zvcm1TdHJlYW08XG4gIFVpbnQ4QXJyYXksXG4gIFVpbnQ4QXJyYXlcbj4ge1xuICBsZXQgYnVmZmVyID0gbmV3IFVpbnQ4QXJyYXkoMCk7XG5cbiAgZnVuY3Rpb24gYXBwZW5kVG9CdWZmZXIoZGF0YTogVWludDhBcnJheSkge1xuICAgIGNvbnN0IG5leHQgPSBuZXcgVWludDhBcnJheShidWZmZXIubGVuZ3RoICsgZGF0YS5sZW5ndGgpO1xuICAgIG5leHQuc2V0KGJ1ZmZlciwgMCk7XG4gICAgbmV4dC5zZXQoZGF0YSwgYnVmZmVyLmxlbmd0aCk7XG4gICAgYnVmZmVyID0gbmV4dDtcbiAgfVxuXG4gIHJldHVybiBuZXcgVHJhbnNmb3JtU3RyZWFtPFVpbnQ4QXJyYXksIFVpbnQ4QXJyYXk+KHtcbiAgICB0cmFuc2Zvcm0oY2h1bmssIGNvbnRyb2xsZXIpIHtcbiAgICAgIGlmIChjaHVuay5sZW5ndGggPiAwKSBhcHBlbmRUb0J1ZmZlcihjaHVuayk7XG5cbiAgICAgIHdoaWxlIChidWZmZXIubGVuZ3RoID49IEZSQU1FX0hFQURFUl9TSVpFKSB7XG4gICAgICAgIGNvbnN0IGZyYW1lTGVuZ3RoID0gbmV3IERhdGFWaWV3KFxuICAgICAgICAgIGJ1ZmZlci5idWZmZXIsXG4gICAgICAgICAgYnVmZmVyLmJ5dGVPZmZzZXQsXG4gICAgICAgICAgYnVmZmVyLmJ5dGVMZW5ndGhcbiAgICAgICAgKS5nZXRVaW50MzIoMCwgZmFsc2UpO1xuXG4gICAgICAgIGlmIChmcmFtZUxlbmd0aCA+IE1BWF9GUkFNRV9TSVpFKSB7XG4gICAgICAgICAgY29udHJvbGxlci5lcnJvcihcbiAgICAgICAgICAgIG5ldyBXb3JrZmxvd1J1bnRpbWVFcnJvcihcbiAgICAgICAgICAgICAgYEJ5dGUtc3RyZWFtIGZyYW1lIGxlbmd0aCAke2ZyYW1lTGVuZ3RofSBleGNlZWRzIG1heGltdW0gKCR7TUFYX0ZSQU1FX1NJWkV9KS4gYCArXG4gICAgICAgICAgICAgICAgYFRoaXMgdXN1YWxseSBtZWFucyBhIG5vbi1mcmFtZWQgYnl0ZSBzdHJlYW0gaXMgYmVpbmcgcmVhZCBhcyBmcmFtZWQuYCxcbiAgICAgICAgICAgICAgeyBzbHVnOiAnc2VyaWFsaXphdGlvbi1mYWlsZWQnIH1cbiAgICAgICAgICAgIClcbiAgICAgICAgICApO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHRvdGFsID0gRlJBTUVfSEVBREVSX1NJWkUgKyBmcmFtZUxlbmd0aDtcbiAgICAgICAgaWYgKGJ1ZmZlci5sZW5ndGggPCB0b3RhbCkgYnJlYWs7XG5cbiAgICAgICAgY29udHJvbGxlci5lbnF1ZXVlKGJ1ZmZlci5zbGljZShGUkFNRV9IRUFERVJfU0laRSwgdG90YWwpKTtcbiAgICAgICAgYnVmZmVyID0gYnVmZmVyLnNsaWNlKHRvdGFsKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIGZsdXNoKGNvbnRyb2xsZXIpIHtcbiAgICAgIGlmIChidWZmZXIubGVuZ3RoID4gMCkge1xuICAgICAgICBjb250cm9sbGVyLmVycm9yKFxuICAgICAgICAgIG5ldyBXb3JrZmxvd1J1bnRpbWVFcnJvcihcbiAgICAgICAgICAgIGBCeXRlLXN0cmVhbSBlbmRlZCB3aXRoICR7YnVmZmVyLmxlbmd0aH0gYnl0ZXMgb2YgaW5jb21wbGV0ZSBmcmFtZSBkYXRhLiBgICtcbiAgICAgICAgICAgICAgYFRoZSBzdHJlYW0gd2FzIHRydW5jYXRlZCBtaWQtZnJhbWUuYCxcbiAgICAgICAgICAgIHsgc2x1ZzogJ3NlcmlhbGl6YXRpb24tZmFpbGVkJyB9XG4gICAgICAgICAgKVxuICAgICAgICApO1xuICAgICAgfVxuICAgIH0sXG4gIH0pO1xufVxuXG5leHBvcnQgY2xhc3MgV29ya2Zsb3dTZXJ2ZXJSZWFkYWJsZVN0cmVhbSBleHRlbmRzIFJlYWRhYmxlU3RyZWFtPFVpbnQ4QXJyYXk+IHtcbiAgI3JlYWRlcj86IFJlYWRhYmxlU3RyZWFtRGVmYXVsdFJlYWRlcjxVaW50OEFycmF5PjtcblxuICBjb25zdHJ1Y3RvcihydW5JZDogc3RyaW5nLCBuYW1lOiBzdHJpbmcsIHN0YXJ0SW5kZXg/OiBudW1iZXIpIHtcbiAgICBpZiAodHlwZW9mIG5hbWUgIT09ICdzdHJpbmcnIHx8IG5hbWUubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgV29ya2Zsb3dSdW50aW1lRXJyb3IoYFwibmFtZVwiIGlzIHJlcXVpcmVkLCBnb3QgXCIke25hbWV9XCJgKTtcbiAgICB9XG4gICAgc3VwZXIoe1xuICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciBOb3Qgc3VyZSB3aHkgVHlwZVNjcmlwdCBpcyBjb21wbGFpbmluZyBhYm91dCB0aGlzXG4gICAgICB0eXBlOiAnYnl0ZXMnLFxuXG4gICAgICBwdWxsOiBhc3luYyAoY29udHJvbGxlcikgPT4ge1xuICAgICAgICBsZXQgcmVhZGVyID0gdGhpcy4jcmVhZGVyO1xuICAgICAgICBpZiAoIXJlYWRlcikge1xuICAgICAgICAgIGNvbnN0IHdvcmxkID0gYXdhaXQgZ2V0V29ybGRMYXp5KCk7XG4gICAgICAgICAgY29uc3Qgc3RyZWFtID0gYXdhaXQgd29ybGQuc3RyZWFtcy5nZXQocnVuSWQsIG5hbWUsIHN0YXJ0SW5kZXgpO1xuICAgICAgICAgIHJlYWRlciA9IHRoaXMuI3JlYWRlciA9IHN0cmVhbS5nZXRSZWFkZXIoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXJlYWRlcikge1xuICAgICAgICAgIGNvbnRyb2xsZXIuZXJyb3IobmV3IEVycm9yKCdGYWlsZWQgdG8gZ2V0IHJlYWRlcicpKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCByZWFkZXIucmVhZCgpO1xuICAgICAgICBpZiAocmVzdWx0LmRvbmUpIHtcbiAgICAgICAgICB0aGlzLiNyZWFkZXIgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgY29udHJvbGxlci5jbG9zZSgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIEZvcndhcmQgcmF3IGJ5dGVzOyBlbmNyeXB0aW9uL2RlY3J5cHRpb24gaXMgaGFuZGxlZCBhdCB0aGVcbiAgICAgICAgICAvLyBmcmFtaW5nIGxldmVsIGJ5IGdldFNlcmlhbGl6ZVN0cmVhbS9nZXREZXNlcmlhbGl6ZVN0cmVhbS5cbiAgICAgICAgICBjb250cm9sbGVyLmVucXVldWUocmVzdWx0LnZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIGNhbmNlbDogYXN5bmMgKHJlYXNvbikgPT4ge1xuICAgICAgICBpZiAodGhpcy4jcmVhZGVyKSB7XG4gICAgICAgICAgYXdhaXQgdGhpcy4jcmVhZGVyLmNhbmNlbChyZWFzb24pLmNhdGNoKCgpID0+IHt9KTtcbiAgICAgICAgICB0aGlzLiNyZWFkZXIgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cbn1cblxuLyoqXG4gKiBNYXhpbXVtIGNvbnNlY3V0aXZlIHJlY29ubmVjdCBhdHRlbXB0cyBmb3IgYSBzaW5nbGUgZnJhbWVkIHN0cmVhbSBzZXNzaW9uLlxuICogVGhlIGNvdW50ZXIgcmVzZXRzIHRvIHplcm8gd2hlbmV2ZXIgYSByZWNvbm5lY3QgbWFrZXMgZm9yd2FyZCBwcm9ncmVzcyAoYVxuICogZnJhbWUgaXMgZGVsaXZlcmVkKSwgc28gdGhpcyBib3VuZHMgKmNvbnNlY3V0aXZlKiBmYWlsdXJlcywgbm90IHRoZSBsaWZldGltZVxuICogdG90YWwg4oCUIGEgbG9uZy1saXZlZCBzZXJ2ZXJsZXNzIHN0cmVhbSBtYXkgbGVnaXRpbWF0ZWx5IHJlY29ubmVjdCBmYXIgbW9yZVxuICogdGhhbiB0aGlzIG1hbnkgdGltZXMgYXMgbG9uZyBhcyBlYWNoIHJlY29ubmVjdCBrZWVwcyBkZWxpdmVyaW5nIGRhdGEuIFdlIG9ubHlcbiAqIGdpdmUgdXAgYWZ0ZXIgdGhpcyBtYW55IHJlY29ubmVjdHMgaW4gYSByb3cgcHJvZHVjZSBub3RoaW5nLlxuICovXG5leHBvcnQgY29uc3QgRlJBTUVEX1NUUkVBTV9NQVhfUkVDT05ORUNUUyA9IDUwO1xuXG4vKipcbiAqIEFic29sdXRlIGJhY2tzdG9wIG9uIHRvdGFsIHJlY29ubmVjdHMgZm9yIGEgc2luZ2xlIHNlc3Npb24sIGluZGVwZW5kZW50IG9mXG4gKiBwcm9ncmVzcy4gVGhlIGNvbnNlY3V0aXZlIGNhcCBhYm92ZSByZXNldHMgb24gZm9yd2FyZCBwcm9ncmVzcywgd2hpY2ggaXNcbiAqIGNvcnJlY3QgZm9yIGEgd2VsbC1iZWhhdmVkIGJhY2tlbmQgdGhhdCBob25vcnMgYHN0YXJ0SW5kZXhgLiBCdXQgaWYgYSBXb3JsZCdzXG4gKiBgc3RyZWFtcy5nZXRgIGV2ZXIgaWdub3JlZCBgc3RhcnRJbmRleGAgYW5kIHJlLWRlbGl2ZXJlZCBlYXJsaWVyIGNodW5rcyxcbiAqIFwicHJvZ3Jlc3NcIiB3b3VsZCBiZSByZXBvcnRlZCBldmVyeSByZWNvbm5lY3QgYW5kIHRoZSBjb25zZWN1dGl2ZSBjYXAgd291bGRcbiAqIG5ldmVyIHRyaXAg4oCUIHR1cm5pbmcgYSBib3VuZGVkIGZhaWx1cmUgaW50byBhbiB1bmJvdW5kZWQgcmVjb25uZWN0IGxvb3AuIFRoaXNcbiAqIGhhcmQgY2VpbGluZyBndWFyYW50ZWVzIHRoZSBsb29wIGFsd2F5cyB0ZXJtaW5hdGVzLiBJdCBpcyBzZXQgaGlnaCBlbm91Z2hcbiAqIChob3VycyBvZiBzdHJlYW1pbmcgYXQgcmVhbGlzdGljIHBlci1zZXNzaW9uIHRpbWVvdXRzKSB0byBuZXZlciBpbnRlcmZlcmVcbiAqIHdpdGggbGVnaXRpbWF0ZSBsb25nLWxpdmVkIHN0cmVhbXMuXG4gKi9cbmV4cG9ydCBjb25zdCBGUkFNRURfU1RSRUFNX01BWF9UT1RBTF9SRUNPTk5FQ1RTID0gMTAwMDtcblxuLyoqXG4gKiBXcmFwcyB0aGUgbGVuZ3RoLXByZWZpeC1mcmFtZWQgYnl0ZSBzdHJlYW0gZnJvbSBgd29ybGQuc3RyZWFtcy5nZXRgIHdpdGhcbiAqIHRyYW5zcGFyZW50IGF1dG8tcmVjb25uZWN0LlxuICpcbiAqIEV2ZXJ5IGZ1bGx5LWRlY29kZWQgb3V0ZXIgZnJhbWUgY29ycmVzcG9uZHMgdG8gZXhhY3RseSBvbmUgc2VydmVyLXNpZGVcbiAqIGNodW5rICh0aGUgc2VyaWFsaXplIHRyYW5zZm9ybSBlbnF1ZXVlcyBvbmUgZnJhbWUgcGVyIHdvcmtmbG93IHdyaXRlLCBhbmRcbiAqIHRoZSB3cml0YWJsZSBidWZmZXJzIG9uZSBmcmFtZSBwZXIgY2h1bmsgd2hlbiBtdWx0aS13cml0aW5nKS4gVGhlIHdyYXBwZXJcbiAqIGNvdW50cyBjb21wbGV0ZWQgZnJhbWVzIGFuZCwgb24gdXBzdHJlYW0gZXJyb3IsIHJlb3BlbnMgdGhlIGNvbm5lY3Rpb25cbiAqIHdpdGggYHN0YXJ0SW5kZXggPSByZXNvbHZlZFN0YXJ0SW5kZXggKyBjb25zdW1lZEZyYW1lc2AuIFBhcnRpYWwtZnJhbWVcbiAqIGJ5dGVzIGJ1ZmZlcmVkIGJlZm9yZSB0aGUgY3V0IGFyZSBkaXNjYXJkZWQg4oCUIHRoZSBzZXJ2ZXIgd2lsbCByZXNlbmQgdGhlXG4gKiBpbi1mbGlnaHQgY2h1bmsgaW4gZnVsbCBmcm9tIHRoZSBuZXcgc3RhcnRJbmRleC5cbiAqXG4gKiBBIGNsZWFuIHVwc3RyZWFtIGNsb3NlIChFT0Ygd2l0aCBubyBlcnJvcikgc2lnbmFscyB0aGUgc3RyZWFtIGlzIHRydWx5XG4gKiBkb25lOyB3ZSBjbG9zZSB0aGUgd3JhcHBlciBhbmQgZG8gbm90IHJlY29ubmVjdC5cbiAqXG4gKiBOZWdhdGl2ZSBgc3RhcnRJbmRleGAgdmFsdWVzIChsYXN0LU4gc2VtYW50aWNzKSBza2lwIHRoZSByZWNvbm5lY3RcbiAqIG1hY2hpbmVyeSBiZWNhdXNlIHdlIGNhbm5vdCBjb21wdXRlIGFuIGFic29sdXRlIHJlc3VtZSBwb3NpdGlvbiB3aXRob3V0XG4gKiBhIHRhaWwtaW5kZXggbG9va3VwIOKAlCB0aGUgcmV0dXJuZWQgc3RyZWFtIGJlaGF2ZXMgYXMgYSBzaW5nbGUtc2hvdCByZWFkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlUmVjb25uZWN0aW5nRnJhbWVkU3RyZWFtKFxuICBydW5JZDogc3RyaW5nLFxuICBuYW1lOiBzdHJpbmcsXG4gIHN0YXJ0SW5kZXg/OiBudW1iZXJcbik6IFJlYWRhYmxlU3RyZWFtPFVpbnQ4QXJyYXk+IHtcbiAgY29uc3QgcmVjb25uZWN0U3VwcG9ydGVkID0gc3RhcnRJbmRleCA9PT0gdW5kZWZpbmVkIHx8IHN0YXJ0SW5kZXggPj0gMDtcbiAgbGV0IGN1cnJlbnRTdGFydEluZGV4ID0gc3RhcnRJbmRleCA/PyAwO1xuICBsZXQgY29uc3VtZWRGcmFtZXMgPSAwO1xuICBsZXQgcmVjb25uZWN0Q291bnQgPSAwO1xuICBsZXQgdG90YWxSZWNvbm5lY3RDb3VudCA9IDA7XG4gIGxldCByZWFkZXI6IFJlYWRhYmxlU3RyZWFtRGVmYXVsdFJlYWRlcjxVaW50OEFycmF5PiB8IHVuZGVmaW5lZDtcbiAgbGV0IGJ1ZmZlciA9IG5ldyBVaW50OEFycmF5KDApO1xuXG4gIGFzeW5jIGZ1bmN0aW9uIGNvbm5lY3QoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3Qgd29ybGQgPSBhd2FpdCBnZXRXb3JsZExhenkoKTtcbiAgICBjb25zdCBlZmZlY3RpdmVTdGFydEluZGV4ID0gcmVjb25uZWN0U3VwcG9ydGVkXG4gICAgICA/IGN1cnJlbnRTdGFydEluZGV4ICsgY29uc3VtZWRGcmFtZXNcbiAgICAgIDogc3RhcnRJbmRleDtcbiAgICBjb25zdCBzdHJlYW0gPSBhd2FpdCB3b3JsZC5zdHJlYW1zLmdldChydW5JZCwgbmFtZSwgZWZmZWN0aXZlU3RhcnRJbmRleCk7XG4gICAgcmVhZGVyID0gc3RyZWFtLmdldFJlYWRlcigpO1xuICB9XG5cbiAgYXN5bmMgZnVuY3Rpb24gcmVjb25uZWN0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJlY29ubmVjdENvdW50Kys7XG4gICAgdG90YWxSZWNvbm5lY3RDb3VudCsrO1xuICAgIGlmIChyZWNvbm5lY3RDb3VudCA+IEZSQU1FRF9TVFJFQU1fTUFYX1JFQ09OTkVDVFMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFN0cmVhbSBcIiR7bmFtZX1cIiBleGNlZWRlZCBtYXhpbXVtIHJlY29ubmVjdGlvbiBhdHRlbXB0cyAoJHtGUkFNRURfU1RSRUFNX01BWF9SRUNPTk5FQ1RTfSlgXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAodG90YWxSZWNvbm5lY3RDb3VudCA+IEZSQU1FRF9TVFJFQU1fTUFYX1RPVEFMX1JFQ09OTkVDVFMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFN0cmVhbSBcIiR7bmFtZX1cIiBleGNlZWRlZCBtYXhpbXVtIHRvdGFsIHJlY29ubmVjdGlvbiBhdHRlbXB0cyAoJHtGUkFNRURfU1RSRUFNX01BWF9UT1RBTF9SRUNPTk5FQ1RTfSlgXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAocmVhZGVyKSB7XG4gICAgICBhd2FpdCByZWFkZXIuY2FuY2VsKCkuY2F0Y2goKCkgPT4ge30pO1xuICAgICAgcmVhZGVyID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgICBjdXJyZW50U3RhcnRJbmRleCArPSBjb25zdW1lZEZyYW1lcztcbiAgICBjb25zdW1lZEZyYW1lcyA9IDA7XG4gICAgYnVmZmVyID0gbmV3IFVpbnQ4QXJyYXkoMCk7XG4gICAgYXdhaXQgY29ubmVjdCgpO1xuICB9XG5cbiAgcmV0dXJuIG5ldyBSZWFkYWJsZVN0cmVhbTxVaW50OEFycmF5Pih7XG4gICAgcHVsbDogYXN5bmMgKGNvbnRyb2xsZXIpID0+IHtcbiAgICAgIC8vIExvb3AgdW50aWwgd2UgZW1pdCBzb21ldGhpbmcsIGhpdCBFT0YsIG9yIGZhdGFsbHkgZXJyb3IuIFJlYWRzIHRoYXRcbiAgICAgIC8vIG9ubHkgZXh0ZW5kIHRoZSBpbi1mbGlnaHQtZnJhbWUgYnVmZmVyIGRvbid0IGVucXVldWUgYW55dGhpbmcg4oCUIHdlXG4gICAgICAvLyBrZWVwIHJlYWRpbmcgcmF0aGVyIHRoYW4gcmV0dXJuaW5nIGVtcHR5LWhhbmRlZC5cbiAgICAgIGZvciAoOzspIHtcbiAgICAgICAgaWYgKCFyZWFkZXIpIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgY29ubmVjdCgpO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgY29udHJvbGxlci5lcnJvcihlcnIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGxldCByZXN1bHQ6IHsgZG9uZTogYm9vbGVhbjsgdmFsdWU/OiBVaW50OEFycmF5IH07XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3R5bGUvbm9Ob25OdWxsQXNzZXJ0aW9uOiBjb25uZWN0KCkgZ3VhcmFudGVlcyByZWFkZXJcbiAgICAgICAgICByZXN1bHQgPSBhd2FpdCByZWFkZXIhLnJlYWQoKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgaWYgKCFyZWNvbm5lY3RTdXBwb3J0ZWQpIHtcbiAgICAgICAgICAgIGNvbnRyb2xsZXIuZXJyb3IoZXJyKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IHJlY29ubmVjdCgpO1xuICAgICAgICAgIH0gY2F0Y2ggKHJlY29ubmVjdEVycikge1xuICAgICAgICAgICAgY29udHJvbGxlci5lcnJvcihyZWNvbm5lY3RFcnIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChyZXN1bHQuZG9uZSB8fCAhcmVzdWx0LnZhbHVlKSB7XG4gICAgICAgICAgLy8gQ2xlYW4gRU9GIOKAlCBzdHJlYW0gaXMgdHJ1bHkgY29tcGxldGUuIERyb3AgYW55IHBhcnRpYWwtZnJhbWVcbiAgICAgICAgICAvLyBieXRlcyAodGhlcmUgc2hvdWxkbid0IGJlIGFueTsgYSB3ZWxsLWZvcm1lZCBzdHJlYW0gZW5kcyBvbiBhXG4gICAgICAgICAgLy8gZnJhbWUgYm91bmRhcnkpLlxuICAgICAgICAgIHJlYWRlciA9IHVuZGVmaW5lZDtcbiAgICAgICAgICBjb250cm9sbGVyLmNsb3NlKCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQXBwZW5kIHRvIGJ1ZmZlciBhbmQgZW1pdCBhbGwgY29tcGxldGUgZnJhbWVzLlxuICAgICAgICBjb25zdCBpbmNvbWluZyA9IHJlc3VsdC52YWx1ZTtcbiAgICAgICAgaWYgKGluY29taW5nLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBjb25zdCBjb21iaW5lZCA9IG5ldyBVaW50OEFycmF5KGJ1ZmZlci5sZW5ndGggKyBpbmNvbWluZy5sZW5ndGgpO1xuICAgICAgICAgIGNvbWJpbmVkLnNldChidWZmZXIsIDApO1xuICAgICAgICAgIGNvbWJpbmVkLnNldChpbmNvbWluZywgYnVmZmVyLmxlbmd0aCk7XG4gICAgICAgICAgYnVmZmVyID0gY29tYmluZWQ7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgZW1pdHRlZCA9IGZhbHNlO1xuICAgICAgICB3aGlsZSAoYnVmZmVyLmxlbmd0aCA+PSBGUkFNRV9IRUFERVJfU0laRSkge1xuICAgICAgICAgIGNvbnN0IGZyYW1lTGVuZ3RoID0gbmV3IERhdGFWaWV3KFxuICAgICAgICAgICAgYnVmZmVyLmJ1ZmZlcixcbiAgICAgICAgICAgIGJ1ZmZlci5ieXRlT2Zmc2V0LFxuICAgICAgICAgICAgYnVmZmVyLmJ5dGVMZW5ndGhcbiAgICAgICAgICApLmdldFVpbnQzMigwLCBmYWxzZSk7XG4gICAgICAgICAgY29uc3QgdG90YWwgPSBGUkFNRV9IRUFERVJfU0laRSArIGZyYW1lTGVuZ3RoO1xuICAgICAgICAgIGlmIChidWZmZXIubGVuZ3RoIDwgdG90YWwpIGJyZWFrO1xuICAgICAgICAgIC8vIEZvcndhcmQgdGhlIGVudGlyZSBmcmFtZWQgY2h1bmsgKGhlYWRlciArIHBheWxvYWQpIHRvIHRoZVxuICAgICAgICAgIC8vIGRvd25zdHJlYW0gZGVzZXJpYWxpemVyLCB3aGljaCBhbHJlYWR5IGV4cGVjdHMgdGhpcyBsYXlvdXQuXG4gICAgICAgICAgY29udHJvbGxlci5lbnF1ZXVlKGJ1ZmZlci5zbGljZSgwLCB0b3RhbCkpO1xuICAgICAgICAgIGJ1ZmZlciA9IGJ1ZmZlci5zbGljZSh0b3RhbCk7XG4gICAgICAgICAgY29uc3VtZWRGcmFtZXMrKztcbiAgICAgICAgICBlbWl0dGVkID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChlbWl0dGVkKSB7XG4gICAgICAgICAgLy8gRm9yd2FyZCBwcm9ncmVzcyBvbiB0aGUgY3VycmVudCBjb25uZWN0aW9uIOKAlCBjbGVhciB0aGVcbiAgICAgICAgICAvLyBjb25zZWN1dGl2ZS1mYWlsdXJlIGJ1ZGdldCBzbyBhIGxvbmcgc3RyZWFtIHRoYXQgcmVjb25uZWN0c1xuICAgICAgICAgIC8vIG1hbnkgdGltZXMgKGJ1dCBrZWVwcyBkZWxpdmVyaW5nKSBpcyBuZXZlciBmYWxzZWx5IGNhcHBlZC5cbiAgICAgICAgICByZWNvbm5lY3RDb3VudCA9IDA7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIE9ubHkgcGFydGlhbCBieXRlcyDigJQgcmVhZCBtb3JlLlxuICAgICAgfVxuICAgIH0sXG4gICAgY2FuY2VsOiBhc3luYyAoKSA9PiB7XG4gICAgICBpZiAocmVhZGVyKSB7XG4gICAgICAgIGF3YWl0IHJlYWRlci5jYW5jZWwoKS5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICAgICAgY29uc29sZS53YXJuKCdFcnJvciBjbG9zaW5nIFJlYWRhYmxlU3RyZWFtIHJlYWRlcjonLCBlcnIpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmVhZGVyID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgIH0sXG4gIH0pO1xufVxuXG4vKipcbiAqIERlZmF1bHQgZmx1c2ggaW50ZXJ2YWwgaW4gbWlsbGlzZWNvbmRzIGZvciBidWZmZXJlZCBzdHJlYW0gd3JpdGVzLlxuICogQ2h1bmtzIGFyZSBhY2N1bXVsYXRlZCBhbmQgZmx1c2hlZCB0b2dldGhlciB0byByZWR1Y2UgbmV0d29yayBvdmVyaGVhZC5cbiAqL1xuY29uc3QgU1RSRUFNX0ZMVVNIX0lOVEVSVkFMX01TID0gMTA7XG5cbmV4cG9ydCBjbGFzcyBXb3JrZmxvd1NlcnZlcldyaXRhYmxlU3RyZWFtIGV4dGVuZHMgV3JpdGFibGVTdHJlYW08VWludDhBcnJheT4ge1xuICBjb25zdHJ1Y3RvcihydW5JZDogc3RyaW5nLCBuYW1lOiBzdHJpbmcpIHtcbiAgICBpZiAodHlwZW9mIHJ1bklkICE9PSAnc3RyaW5nJykge1xuICAgICAgdGhyb3cgbmV3IFdvcmtmbG93UnVudGltZUVycm9yKFxuICAgICAgICBgXCJydW5JZFwiIG11c3QgYmUgYSBzdHJpbmcsIGdvdCBcIiR7dHlwZW9mIHJ1bklkfVwiYFxuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBuYW1lICE9PSAnc3RyaW5nJyB8fCBuYW1lLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IFdvcmtmbG93UnVudGltZUVycm9yKGBcIm5hbWVcIiBpcyByZXF1aXJlZCwgZ290IFwiJHtuYW1lfVwiYCk7XG4gICAgfVxuICAgIGNvbnN0IHdvcmxkUHJvbWlzZSA9IGdldFdvcmxkTGF6eSgpO1xuXG4gICAgLy8gQnVmZmVyaW5nIHN0YXRlIGZvciBiYXRjaGVkIHdyaXRlc1xuICAgIC8vIEVuY3J5cHRpb24vZGVjcnlwdGlvbiBpcyBoYW5kbGVkIGF0IHRoZSBmcmFtaW5nIGxldmVsIGJ5XG4gICAgLy8gZ2V0U2VyaWFsaXplU3RyZWFtL2dldERlc2VyaWFsaXplU3RyZWFtLCBub3QgaGVyZS5cbiAgICBsZXQgYnVmZmVyOiBVaW50OEFycmF5W10gPSBbXTtcbiAgICBsZXQgZmx1c2hUaW1lcjogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0VGltZW91dD4gfCBudWxsID0gbnVsbDtcbiAgICBsZXQgZmx1c2hQcm9taXNlOiBQcm9taXNlPHZvaWQ+IHwgbnVsbCA9IG51bGw7XG4gICAgbGV0IHJlc29sdmVkRmx1c2hJbnRlcnZhbE1zOiBudW1iZXIgfCB1bmRlZmluZWQ7XG5cbiAgICBjb25zdCBmbHVzaCA9IGFzeW5jICgpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICAgIGlmIChmbHVzaFRpbWVyKSB7XG4gICAgICAgIGNsZWFyVGltZW91dChmbHVzaFRpbWVyKTtcbiAgICAgICAgZmx1c2hUaW1lciA9IG51bGw7XG4gICAgICB9XG5cbiAgICAgIGlmIChidWZmZXIubGVuZ3RoID09PSAwKSByZXR1cm47XG5cbiAgICAgIC8vIENvcHkgY2h1bmtzIHRvIGZsdXNoLCBidXQgZG9uJ3QgY2xlYXIgYnVmZmVyIHVudGlsIHdyaXRlIHN1Y2NlZWRzXG4gICAgICAvLyBUaGlzIHByZXZlbnRzIGRhdGEgbG9zcyBpZiB0aGUgd3JpdGUgb3BlcmF0aW9uIGZhaWxzXG4gICAgICBjb25zdCBjaHVua3NUb0ZsdXNoID0gYnVmZmVyLnNsaWNlKCk7XG5cbiAgICAgIGNvbnN0IHdvcmxkID0gYXdhaXQgd29ybGRQcm9taXNlO1xuICAgICAgLy8gQ2FjaGUgdGhlIGZsdXNoIGludGVydmFsIGZyb20gdGhlIHdvcmxkIG9uIGZpcnN0IHVzZVxuICAgICAgaWYgKHJlc29sdmVkRmx1c2hJbnRlcnZhbE1zID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmVzb2x2ZWRGbHVzaEludGVydmFsTXMgPVxuICAgICAgICAgIHdvcmxkLnN0cmVhbUZsdXNoSW50ZXJ2YWxNcyA/PyBTVFJFQU1fRkxVU0hfSU5URVJWQUxfTVM7XG4gICAgICB9XG4gICAgICAvLyBVc2Ugd3JpdGVNdWx0aSBpZiBhdmFpbGFibGUgZm9yIGJhdGNoIHdyaXRlc1xuICAgICAgaWYgKFxuICAgICAgICB0eXBlb2Ygd29ybGQuc3RyZWFtcy53cml0ZU11bHRpID09PSAnZnVuY3Rpb24nICYmXG4gICAgICAgIGNodW5rc1RvRmx1c2gubGVuZ3RoID4gMVxuICAgICAgKSB7XG4gICAgICAgIGF3YWl0IHdvcmxkLnN0cmVhbXMud3JpdGVNdWx0aShydW5JZCwgbmFtZSwgY2h1bmtzVG9GbHVzaCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBGYWxsIGJhY2sgdG8gc2VxdWVudGlhbCB3cml0ZXNcbiAgICAgICAgZm9yIChjb25zdCBjaHVuayBvZiBjaHVua3NUb0ZsdXNoKSB7XG4gICAgICAgICAgYXdhaXQgd29ybGQuc3RyZWFtcy53cml0ZShydW5JZCwgbmFtZSwgY2h1bmspO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIE9ubHkgY2xlYXIgYnVmZmVyIGFmdGVyIHN1Y2Nlc3NmdWwgd3JpdGUgdG8gcHJldmVudCBkYXRhIGxvc3NcbiAgICAgIGJ1ZmZlciA9IFtdO1xuICAgIH07XG5cbiAgICAvKiogUmVzb2x2ZXJzL3JlamVjdG9ycyB3YWl0aW5nIGZvciB0aGUgY3VycmVudCBzY2hlZHVsZWQgZmx1c2ggKi9cbiAgICBsZXQgZmx1c2hXYWl0ZXJzOiBBcnJheTx7XG4gICAgICByZXNvbHZlOiAoKSA9PiB2b2lkO1xuICAgICAgcmVqZWN0OiAoZXJyOiB1bmtub3duKSA9PiB2b2lkO1xuICAgIH0+ID0gW107XG5cbiAgICBjb25zdCBzY2hlZHVsZUZsdXNoID0gKCk6IHZvaWQgPT4ge1xuICAgICAgaWYgKGZsdXNoVGltZXIpIHJldHVybjsgLy8gQWxyZWFkeSBzY2hlZHVsZWRcblxuICAgICAgZmx1c2hUaW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICBmbHVzaFRpbWVyID0gbnVsbDtcbiAgICAgICAgY29uc3QgY3VycmVudFdhaXRlcnMgPSBmbHVzaFdhaXRlcnM7XG4gICAgICAgIGZsdXNoV2FpdGVycyA9IFtdO1xuICAgICAgICBmbHVzaFByb21pc2UgPSBmbHVzaCgpLnRoZW4oXG4gICAgICAgICAgKCkgPT4ge1xuICAgICAgICAgICAgZm9yIChjb25zdCB3IG9mIGN1cnJlbnRXYWl0ZXJzKSB3LnJlc29sdmUoKTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIChlcnIpID0+IHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgdyBvZiBjdXJyZW50V2FpdGVycykgdy5yZWplY3QoZXJyKTtcbiAgICAgICAgICB9XG4gICAgICAgICk7XG4gICAgICB9LCByZXNvbHZlZEZsdXNoSW50ZXJ2YWxNcyA/PyBTVFJFQU1fRkxVU0hfSU5URVJWQUxfTVMpO1xuICAgIH07XG5cbiAgICBzdXBlcih7XG4gICAgICBhc3luYyB3cml0ZShjaHVuaykge1xuICAgICAgICAvLyBXYWl0IGZvciBhbnkgaW4tcHJvZ3Jlc3MgZmx1c2ggdG8gY29tcGxldGUgYmVmb3JlIGFkZGluZyB0byBidWZmZXJcbiAgICAgICAgaWYgKGZsdXNoUHJvbWlzZSkge1xuICAgICAgICAgIGF3YWl0IGZsdXNoUHJvbWlzZTtcbiAgICAgICAgICBmbHVzaFByb21pc2UgPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgYnVmZmVyLnB1c2goY2h1bmspO1xuICAgICAgICBzY2hlZHVsZUZsdXNoKCk7XG5cbiAgICAgICAgLy8gV2FpdCBmb3IgdGhlIHNjaGVkdWxlZCBmbHVzaCB0byBjb21wbGV0ZSBzbyB0aGF0IGNhbGxlcnNcbiAgICAgICAgLy8gKGxpa2UgZmx1c2hhYmxlUGlwZSkga25vdyBkYXRhIGhhcyByZWFjaGVkIHRoZSBzZXJ2ZXJcbiAgICAgICAgLy8gYmVmb3JlIGRlY3JlbWVudGluZyBwZW5kaW5nT3BzLiBXaXRob3V0IHRoaXMsIHBlbmRpbmdPcHNcbiAgICAgICAgLy8gcmVhY2hlcyAwIHdoZW4gdGhlIGJ1ZmZlcmVkIHdyaXRlIHJldHVybnMgKGluc3RhbnQpLCBidXRcbiAgICAgICAgLy8gdGhlIDEwbXMgZmx1c2ggdGltZXIgaGFzbid0IGZpcmVkIHlldC5cbiAgICAgICAgYXdhaXQgbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgIGZsdXNoV2FpdGVycy5wdXNoKHsgcmVzb2x2ZSwgcmVqZWN0IH0pO1xuICAgICAgICB9KTtcbiAgICAgIH0sXG4gICAgICBhc3luYyBjbG9zZSgpIHtcbiAgICAgICAgLy8gV2FpdCBmb3IgYW55IGluLXByb2dyZXNzIGZsdXNoIHRvIGNvbXBsZXRlXG4gICAgICAgIGlmIChmbHVzaFByb21pc2UpIHtcbiAgICAgICAgICBhd2FpdCBmbHVzaFByb21pc2U7XG4gICAgICAgICAgZmx1c2hQcm9taXNlID0gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEZsdXNoIGFueSByZW1haW5pbmcgYnVmZmVyZWQgY2h1bmtzXG4gICAgICAgIGF3YWl0IGZsdXNoKCk7XG5cbiAgICAgICAgY29uc3Qgd29ybGQgPSBhd2FpdCB3b3JsZFByb21pc2U7XG4gICAgICAgIGF3YWl0IHdvcmxkLnN0cmVhbXMuY2xvc2UocnVuSWQsIG5hbWUpO1xuICAgICAgfSxcbiAgICAgIGFib3J0KHJlYXNvbikge1xuICAgICAgICAvLyBDbGVhbiB1cCB0aW1lciB0byBwcmV2ZW50IGxlYWtzXG4gICAgICAgIGlmIChmbHVzaFRpbWVyKSB7XG4gICAgICAgICAgY2xlYXJUaW1lb3V0KGZsdXNoVGltZXIpO1xuICAgICAgICAgIGZsdXNoVGltZXIgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIC8vIERpc2NhcmQgYnVmZmVyZWQgY2h1bmtzIC0gdGhleSB3b24ndCBiZSB3cml0dGVuXG4gICAgICAgIGJ1ZmZlciA9IFtdO1xuICAgICAgICAvLyBSZWplY3QgYW55IHBlbmRpbmcgZmx1c2hXYWl0ZXJzIHNvIHRoZSB3cml0ZSgpIHByb21pc2VzIHNldHRsZVxuICAgICAgICAvLyBhbmQgZG9uJ3QgbGVhay4gV2l0aG91dCB0aGlzLCB3cml0ZSgpIGhhbmdzIGZvcmV2ZXIgb24gYW5cbiAgICAgICAgLy8gdW5zZXR0bGVkIHByb21pc2UgYmVjYXVzZSB0aGUgY2xlYXJlZCB0aW1lciB3aWxsIG5ldmVyIGZpcmUuXG4gICAgICAgIGNvbnN0IHdhaXRlcnMgPSBmbHVzaFdhaXRlcnM7XG4gICAgICAgIGZsdXNoV2FpdGVycyA9IFtdO1xuICAgICAgICBjb25zdCBhYm9ydEVycm9yID0gcmVhc29uID8/IG5ldyBFcnJvcignU3RyZWFtIGFib3J0ZWQnKTtcbiAgICAgICAgZm9yIChjb25zdCB3IG9mIHdhaXRlcnMpIHcucmVqZWN0KGFib3J0RXJyb3IpO1xuICAgICAgfSxcbiAgICB9KTtcbiAgfVxufVxuXG4vLyBSZS1leHBvcnQgdHlwZXMgZnJvbSB0aGUgbW9kdWxhciBzZXJpYWxpemF0aW9uIG1vZHVsZXMuXG5leHBvcnQgdHlwZSB7XG4gIEJ5dGVTdHJlYW1GcmFtaW5nLFxuICBSZWR1Y2VycyxcbiAgUmV2aXZlcnMsXG4gIFNlcmlhbGl6YWJsZVNwZWNpYWwsXG59IGZyb20gJy4vc2VyaWFsaXphdGlvbi90eXBlcy5qcyc7XG5cbi8vIEltcG9ydCB0eXBlcyBsb2NhbGx5IGZvciB1c2Ugd2l0aGluIHRoaXMgZmlsZS5cbmltcG9ydCB0eXBlIHtcbiAgQnl0ZVN0cmVhbUZyYW1pbmcsXG4gIFJlZHVjZXJzLFxuICBSZXZpdmVycyxcbiAgU2VyaWFsaXphYmxlU3BlY2lhbCxcbn0gZnJvbSAnLi9zZXJpYWxpemF0aW9uL3R5cGVzLmpzJztcblxuLy8gLS0tLSBDb21wb3NlZCByZWR1Y2VycyAtLS0tXG4vLyBDb21wb3NlcyBtb2R1bGFyIHJlZHVjZXJzIChjb21tb24sIGNsYXNzLCBzdGVwLWZ1bmN0aW9uKSB3aXRoXG4vLyBtb2RlLXNwZWNpZmljIFJlcXVlc3QvUmVzcG9uc2UvU3RyZWFtIHJlZHVjZXJzIGJlbG93LlxuXG4vKipcbiAqIEJhc2UgcmVkdWNlcnMgc2hhcmVkIGFjcm9zcyBhbGwgc2VyaWFsaXphdGlvbiBib3VuZGFyaWVzLlxuICogQ29tcG9zZXM6IGNsYXNzICsgc3RlcC1mdW5jdGlvbiArIGNvbW1vbiByZWR1Y2VycyBmcm9tIHRoZSBtb2R1bGFyIG1vZHVsZXMuXG4gKi9cbmZ1bmN0aW9uIGdldEFsbEJhc2VSZWR1Y2VycyhcbiAgZ2xvYmFsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0gZ2xvYmFsVGhpc1xuKTogUGFydGlhbDxSZWR1Y2Vycz4ge1xuICAvLyBDbGFzcy9JbnN0YW5jZSBNVVNUIGNvbWUgYmVmb3JlIEVycm9yIHNvIHRoYXQgY3VzdG9tIEVycm9yIHN1YmNsYXNzZXNcbiAgLy8gd2l0aCBXT1JLRkxPV19TRVJJQUxJWkUgdGFrZSBwcmVjZWRlbmNlIChkZXZhbHVlIHVzZXMgZmlyc3QtbWF0Y2gtd2lucykuXG4gIHJldHVybiB7XG4gICAgLi4uZ2V0Q2xhc3NSZWR1Y2VycygpLFxuICAgIC4uLmdldFN0ZXBGdW5jdGlvblJlZHVjZXIoKSxcbiAgICAuLi5nZXRDb21tb25SZWR1Y2VycyhnbG9iYWwpLFxuICAgIC8vIFJlcXVlc3QgYW5kIFJlc3BvbnNlIHJlZHVjZXJzIGFyZSBtb2RlLXNwZWNpZmljIGFuZCBhZGRlZCBieVxuICAgIC8vIGdldEV4dGVybmFsUmVkdWNlcnMgLyBnZXRXb3JrZmxvd1JlZHVjZXJzIC8gZ2V0U3RlcFJlZHVjZXJzIGJlbG93LlxuICAgIFJlcXVlc3Q6ICh2YWx1ZSkgPT4ge1xuICAgICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBnbG9iYWwuUmVxdWVzdCkpIHJldHVybiBmYWxzZTtcbiAgICAgIGNvbnN0IGRhdGE6IFNlcmlhbGl6YWJsZVNwZWNpYWxbJ1JlcXVlc3QnXSA9IHtcbiAgICAgICAgbWV0aG9kOiB2YWx1ZS5tZXRob2QsXG4gICAgICAgIHVybDogdmFsdWUudXJsLFxuICAgICAgICBoZWFkZXJzOiB2YWx1ZS5oZWFkZXJzLFxuICAgICAgICBib2R5OiB2YWx1ZS5ib2R5LFxuICAgICAgICBkdXBsZXg6IHZhbHVlLmR1cGxleCxcbiAgICAgIH07XG4gICAgICBjb25zdCByZXNwb25zZVdyaXRhYmxlID0gdmFsdWVbV0VCSE9PS19SRVNQT05TRV9XUklUQUJMRV07XG4gICAgICBpZiAocmVzcG9uc2VXcml0YWJsZSkge1xuICAgICAgICBkYXRhLnJlc3BvbnNlV3JpdGFibGUgPSByZXNwb25zZVdyaXRhYmxlO1xuICAgICAgfVxuICAgICAgLy8gRm9yd2FyZCB0aGUgc2lnbmFsIGluIHR3byBjYXNlczpcbiAgICAgIC8vICAgMS4gQWxyZWFkeSBhYm9ydGVkIOKAlCBwcmVzZXJ2ZSBhYm9ydGVkPXRydWUvcmVhc29uIHNvIHRoZSBoeWRyYXRlZFxuICAgICAgLy8gICAgICBzdGVwIHNlZXMgdGhlIGNhbmNlbGxhdGlvbiB0aGF0IGhhcHBlbmVkIGJlZm9yZSBzZXJpYWxpemUuXG4gICAgICAvLyAgIDIuIEFscmVhZHkgdGFnZ2VkIHdpdGggd29ya2Zsb3cgaW5mcmFzdHJ1Y3R1cmUg4oCUIGkuZS4gYSBzaWduYWxcbiAgICAgIC8vICAgICAgZnJvbSBhIHdvcmtmbG93LW1hbmFnZWQgQWJvcnRDb250cm9sbGVyLCB3aGljaCBoYXMgc3RyZWFtL2hvb2tcbiAgICAgIC8vICAgICAgYmFja2luZyBmb3IgY3Jvc3MtYm91bmRhcnkgcHJvcGFnYXRpb24uXG4gICAgICAvLyBQbGFpbiBub24tYWJvcnRlZCBuYXRpdmUgc2lnbmFscyBhcmUgaW50ZW50aW9uYWxseSBkcm9wcGVkICh3b3VsZFxuICAgICAgLy8gbWludCBzdHJlYW0gaW5mcmEgZm9yIGV2ZXJ5IFJlcXVlc3QsIGluY2x1ZGluZyB0aGUgYXV0by1nZW5lcmF0ZWRcbiAgICAgIC8vIHNpZ25hbCBvbiBgbmV3IFJlcXVlc3QodXJsKWApLlxuICAgICAgaWYgKFxuICAgICAgICB2YWx1ZS5zaWduYWwgJiZcbiAgICAgICAgKHZhbHVlLnNpZ25hbC5hYm9ydGVkIHx8XG4gICAgICAgICAgKHZhbHVlLnNpZ25hbCBhcyBBYm9ydEludGVybmFscylbQUJPUlRfU1RSRUFNX05BTUVdKVxuICAgICAgKSB7XG4gICAgICAgIGRhdGEuc2lnbmFsID0gdmFsdWUuc2lnbmFsO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfSxcbiAgICBSZXNwb25zZTogKHZhbHVlKSA9PiB7XG4gICAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIGdsb2JhbC5SZXNwb25zZSkpIHJldHVybiBmYWxzZTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHR5cGU6IHZhbHVlLnR5cGUsXG4gICAgICAgIHVybDogdmFsdWUudXJsLFxuICAgICAgICBzdGF0dXM6IHZhbHVlLnN0YXR1cyxcbiAgICAgICAgc3RhdHVzVGV4dDogdmFsdWUuc3RhdHVzVGV4dCxcbiAgICAgICAgaGVhZGVyczogdmFsdWUuaGVhZGVycyxcbiAgICAgICAgYm9keTogdmFsdWUuYm9keSxcbiAgICAgICAgcmVkaXJlY3RlZDogdmFsdWUucmVkaXJlY3RlZCxcbiAgICAgIH07XG4gICAgfSxcbiAgfTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBTaGFyZWQgYWJvcnQgcmVkdWNlciBoZWxwZXJzXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxudHlwZSBBYm9ydFNlcmlhbGl6ZWREYXRhID0ge1xuICBzdHJlYW1OYW1lOiBzdHJpbmc7XG4gIGhvb2tUb2tlbjogc3RyaW5nO1xuICBhYm9ydGVkOiBib29sZWFuO1xuICByZWFzb246IHVua25vd247XG59O1xuXG4vKipcbiAqIFN5bWJvbC1rZXllZCBpbnRlcm5hbCBmaWVsZHMgdGFnZ2VkIG9udG8gQWJvcnRDb250cm9sbGVyL0Fib3J0U2lnbmFsXG4gKiBpbnN0YW5jZXMgKGFuZCBgaG9sZGVyYHMgaW4gcmVkdWNlciBoZWxwZXJzKS4gQWxsIG9wdGlvbmFsIOKAlCBhIHBsYWluXG4gKiBuYXRpdmUgaW5zdGFuY2UgaGFzIG5vbmUgb2YgdGhlbSBzZXQuXG4gKi9cbnR5cGUgQWJvcnRJbnRlcm5hbHMgPSB7XG4gIFtBQk9SVF9TVFJFQU1fTkFNRV0/OiBzdHJpbmc7XG4gIFtBQk9SVF9IT09LX1RPS0VOXT86IHN0cmluZztcbiAgW0FCT1JUX1JFQURFUl9DQU5DRUxdPzogQWJvcnRDb250cm9sbGVyO1xufTtcblxudHlwZSBBYm9ydFNpZ25hbExpa2UgPSBBYm9ydEludGVybmFscyAmIHtcbiAgYWJvcnRlZDogYm9vbGVhbjtcbiAgcmVhc29uPzogdW5rbm93bjtcbiAgYWRkRXZlbnRMaXN0ZW5lcj86IEZ1bmN0aW9uO1xufTtcblxudHlwZSBBYm9ydEhvbGRlciA9IEFib3J0SW50ZXJuYWxzICYgeyBzaWduYWw/OiBBYm9ydEludGVybmFscyB9O1xuXG4vKipcbiAqIFNoYXJlZCBsb2dpYyBmb3IgQWJvcnRDb250cm9sbGVyL0Fib3J0U2lnbmFsIHJlZHVjZXJzIGluIGV4dGVybmFsIGFuZCBzdGVwXG4gKiBjb250ZXh0cy4gQXNzaWducyBzdHJlYW0vaG9vayBuYW1lcyBpZiBub3QgYWxyZWFkeSBwcmVzZW50LCBvcHRpb25hbGx5XG4gKiBhdHRhY2hlcyBhbiBhYm9ydCBsaXN0ZW5lciBmb3IgcmVhbC10aW1lIHByb3BhZ2F0aW9uLCBhbmQgcmV0dXJucyB0aGVcbiAqIHNlcmlhbGl6ZWQgcmVwcmVzZW50YXRpb24uXG4gKi9cbmZ1bmN0aW9uIHJlZHVjZUFib3J0V2l0aExpc3RlbmVyKFxuICBzaWduYWw6IEFib3J0U2lnbmFsTGlrZSxcbiAgaG9sZGVyOiBBYm9ydEhvbGRlcixcbiAgZ2xvYmFsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICBvcHM6IFByb21pc2U8dm9pZD5bXSxcbiAgcnVuSWQ6IHN0cmluZyxcbiAgY3J5cHRvS2V5OiBFbmNyeXB0aW9uS2V5UGFyYW1cbik6IEFib3J0U2VyaWFsaXplZERhdGEge1xuICBsZXQgc3RyZWFtTmFtZSA9IGhvbGRlcltBQk9SVF9TVFJFQU1fTkFNRV07XG4gIGxldCBob29rVG9rZW4gPSBob2xkZXJbQUJPUlRfSE9PS19UT0tFTl07XG4gIGlmICghc3RyZWFtTmFtZSkge1xuICAgIGNvbnN0IGlkID0gKChnbG9iYWwgYXMgYW55KVtTVEFCTEVfVUxJRF0gfHwgZGVmYXVsdFVsaWQpKCk7XG4gICAgc3RyZWFtTmFtZSA9IGdldEFib3J0U3RyZWFtSWQoaWQpO1xuICAgIGhvb2tUb2tlbiA9IGBhYnJ0XyR7aWR9YDtcbiAgICBob2xkZXJbQUJPUlRfU1RSRUFNX05BTUVdID0gc3RyZWFtTmFtZTtcbiAgICBob2xkZXJbQUJPUlRfSE9PS19UT0tFTl0gPSBob29rVG9rZW47XG4gICAgaWYgKGhvbGRlci5zaWduYWwpIHtcbiAgICAgIGhvbGRlci5zaWduYWxbQUJPUlRfU1RSRUFNX05BTUVdID0gc3RyZWFtTmFtZTtcbiAgICAgIGhvbGRlci5zaWduYWxbQUJPUlRfSE9PS19UT0tFTl0gPSBob29rVG9rZW47XG4gICAgfVxuICB9XG5cbiAgLy8gRGVkdXBlZCB2aWEgQUJPUlRfTElTVEVORVJfQVRUQUNIRUQgbWFya2VyIOKAlCBzZWUgYXR0YWNoQWJvcnRMaXN0ZW5lck9uY2UuXG4gIGF0dGFjaEFib3J0TGlzdGVuZXJPbmNlKFxuICAgIHNpZ25hbCBhcyBBYm9ydFNpZ25hbCxcbiAgICBzdHJlYW1OYW1lLFxuICAgIHJ1bklkLFxuICAgIGNyeXB0b0tleSxcbiAgICBvcHNcbiAgKTtcblxuICByZXR1cm4ge1xuICAgIHN0cmVhbU5hbWUsXG4gICAgaG9va1Rva2VuOiBob29rVG9rZW4hLFxuICAgIGFib3J0ZWQ6IHNpZ25hbC5hYm9ydGVkLFxuICAgIHJlYXNvbjogc2lnbmFsLmFib3J0ZWQgPyBzaWduYWwucmVhc29uIDogdW5kZWZpbmVkLFxuICB9O1xufVxuXG4vKipcbiAqIFNoYXJlZCBsb2dpYyBmb3IgQWJvcnRDb250cm9sbGVyL0Fib3J0U2lnbmFsIHJlZHVjZXJzIGluIHdvcmtmbG93IGNvbnRleHQuXG4gKiBSZWFkcyBleGlzdGluZyBzdHJlYW0vaG9vayBuYW1lcyBmcm9tIHN5bWJvbHMgKG11c3QgYWxyZWFkeSBiZSBzZXQpLlxuICovXG5mdW5jdGlvbiByZWR1Y2VBYm9ydEJ5U3ltYm9sKFxuICBzaWduYWw6IHsgYWJvcnRlZDogYm9vbGVhbjsgcmVhc29uPzogdW5rbm93biB9LFxuICBob2xkZXI6IEFib3J0SG9sZGVyXG4pOiBBYm9ydFNlcmlhbGl6ZWREYXRhIHwgZmFsc2Uge1xuICBjb25zdCBzdHJlYW1OYW1lID1cbiAgICBob2xkZXJbQUJPUlRfU1RSRUFNX05BTUVdID8/IGhvbGRlci5zaWduYWw/LltBQk9SVF9TVFJFQU1fTkFNRV07XG4gIGNvbnN0IGhvb2tUb2tlbiA9XG4gICAgaG9sZGVyW0FCT1JUX0hPT0tfVE9LRU5dID8/IGhvbGRlci5zaWduYWw/LltBQk9SVF9IT09LX1RPS0VOXTtcbiAgaWYgKCFzdHJlYW1OYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdBYm9ydENvbnRyb2xsZXIvQWJvcnRTaWduYWwgc3RyZWFtIG5hbWUgaXMgbm90IHNldCcpO1xuICB9XG4gIHJldHVybiB7XG4gICAgc3RyZWFtTmFtZSxcbiAgICBob29rVG9rZW46IGhvb2tUb2tlbiEsXG4gICAgYWJvcnRlZDogc2lnbmFsLmFib3J0ZWQsXG4gICAgcmVhc29uOiBzaWduYWwuYWJvcnRlZCA/IHNpZ25hbC5yZWFzb24gOiB1bmRlZmluZWQsXG4gIH07XG59XG5cbi8qKlxuICogQXR0YWNoIGEgc2luZ2xlIGFib3J0IGxpc3RlbmVyIHRvIGEgc2lnbmFsLCBkZWR1cGVkIGFjcm9zcyBjYWxscy5cbiAqXG4gKiBFYWNoIHNlcmlhbGl6YXRpb24gcGFzcyBnb2VzIHRocm91Z2ggdGhlIHJlZHVjZXIsIGJ1dCBhIGNvbnRyb2xsZXIgcGFzc2VkXG4gKiB0byBOIHN0ZXBzIHdvdWxkIG90aGVyd2lzZSBhY2N1bXVsYXRlIE4gbGlzdGVuZXJzIOKAlCBlYWNoIHdyaXRpbmcgdGhlIHNhbWVcbiAqIHN0cmVhbSBwYWNrZXQgYW5kIGRvdWJsZS1jbG9zaW5nIHRoZSBzdHJlYW0gb24gYWJvcnQuIFRoZSBtYXJrZXIgc3ltYm9sXG4gKiBlbnN1cmVzIHRoZSBzdHJlYW0td3JpdGUgc2lkZS1lZmZlY3QgcnVucyBhdCBtb3N0IG9uY2UgcGVyIChzaWduYWwsIHJ1bklkKS5cbiAqL1xuZnVuY3Rpb24gYXR0YWNoQWJvcnRMaXN0ZW5lck9uY2UoXG4gIHNpZ25hbDogQWJvcnRTaWduYWwsXG4gIHN0cmVhbU5hbWU6IHN0cmluZyxcbiAgcnVuSWQ6IHN0cmluZyxcbiAgY3J5cHRvS2V5OiBFbmNyeXB0aW9uS2V5UGFyYW0sXG4gIG9wczogUHJvbWlzZTx2b2lkPltdXG4pOiB2b2lkIHtcbiAgaWYgKHNpZ25hbC5hYm9ydGVkKSByZXR1cm47XG4gIGlmICgoc2lnbmFsIGFzIGFueSlbQUJPUlRfTElTVEVORVJfQVRUQUNIRURdKSByZXR1cm47XG4gIChzaWduYWwgYXMgYW55KVtBQk9SVF9MSVNURU5FUl9BVFRBQ0hFRF0gPSB0cnVlO1xuXG4gIHNpZ25hbC5hZGRFdmVudExpc3RlbmVyKFxuICAgICdhYm9ydCcsXG4gICAgKCkgPT4ge1xuICAgICAgb3BzLnB1c2goXG4gICAgICAgIChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIERlaHlkcmF0ZSB2aWEgdGhlIHNhbWUgbWFjaGluZXJ5IHRoZSByZWFkZXIgdXNlcyAoaHlkcmF0ZVN0ZXBBcmd1bWVudHMpXG4gICAgICAgICAgICAvLyBzbyB0aGUgcmVhc29uIHJvdW5kLXRyaXBzIHdpdGggZnVsbCB0eXBlIGZpZGVsaXR5IChET01FeGNlcHRpb24sXG4gICAgICAgICAgICAvLyBFcnJvcnMsIGN1c3RvbSBjbGFzc2VzLCBldGMuKSBhbmQgcmVzcGVjdHMgdGhlIHJ1bidzIGVuY3J5cHRpb24ga2V5LlxuICAgICAgICAgICAgLy8gQSBiYXJlIEpTT04uc3RyaW5naWZ5IGhlcmUgd291bGQgd3JpdGUgYSBwYWNrZXQgdGhlIHJlYWRlciBjYW4ndFxuICAgICAgICAgICAgLy8gZGVjb2RlIGFuZCB0aGUgbGlzdGVuZXItc2lkZSBhYm9ydCB3b3VsZCBwcm9wYWdhdGUgd2l0aCBubyByZWFzb24uXG4gICAgICAgICAgICBjb25zdCBrZXkgPSBhd2FpdCByZXNvbHZlRW5jcnlwdGlvbktleShjcnlwdG9LZXkpO1xuICAgICAgICAgICAgY29uc3QgcGF5bG9hZCA9IGF3YWl0IGRlaHlkcmF0ZVN0ZXBBcmd1bWVudHMoXG4gICAgICAgICAgICAgIHsgYWJvcnRlZDogdHJ1ZSwgcmVhc29uOiBzaWduYWwucmVhc29uIH0sXG4gICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICBrZXlcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjb25zdCB3cml0YWJsZSA9IG5ldyBXb3JrZmxvd1NlcnZlcldyaXRhYmxlU3RyZWFtKFxuICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgc3RyZWFtTmFtZVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNvbnN0IHdyaXRlciA9IHdyaXRhYmxlLmdldFdyaXRlcigpO1xuICAgICAgICAgICAgYXdhaXQgd3JpdGVyLndyaXRlKHBheWxvYWQgYXMgVWludDhBcnJheSk7XG4gICAgICAgICAgICBhd2FpdCB3cml0ZXIuY2xvc2UoKTtcbiAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIC8vIEJlc3QtZWZmb3J0IHN0cmVhbSB3cml0ZVxuICAgICAgICAgIH1cbiAgICAgICAgfSkoKVxuICAgICAgKTtcbiAgICB9LFxuICAgIHsgb25jZTogdHJ1ZSB9XG4gICk7XG59XG5cbi8qKlxuICogUmVkdWNlcnMgZm9yIHNlcmlhbGl6YXRpb24gYm91bmRhcnkgZnJvbSB0aGUgY2xpZW50IHNpZGUsIHBhc3NpbmcgYXJndW1lbnRzXG4gKiB0byB0aGUgd29ya2Zsb3cgaGFuZGxlci5cbiAqXG4gKiBAcGFyYW0gZ2xvYmFsXG4gKiBAcGFyYW0gb3BzXG4gKiBAcGFyYW0gcnVuSWRcbiAqIEBwYXJhbSBjcnlwdG9LZXlcbiAqIEBwYXJhbSBmcmFtZWRCeXRlU3RyZWFtcyAtIFdoZW4gYHRydWVgLCBieXRlIHN0cmVhbXMgKGB0eXBlOiAnYnl0ZXMnYClcbiAqICAgYXJlIHdyYXBwZWQgaW4gbGVuZ3RoLXByZWZpeGVkIGZyYW1lcyBvbiB0aGUgd2lyZSBzbyB0aGUgY29uc3VtZXJcbiAqICAgY2FuIHJlY29ubmVjdCBvbiB0cmFuc2llbnQgZXJyb3JzLiBTaG91bGQgbWF0Y2ggdGhlIHRhcmdldCBydW4nc1xuICogICBjYXBhYmlsaXR5IOKAlCBzZWUgYGdldFJ1bkNhcGFiaWxpdGllc2AgaW4gYGNhcGFiaWxpdGllcy50c2AuIERlZmF1bHRzXG4gKiAgIHRvIGBmYWxzZWAgZm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IHdpdGggb2xkZXIgcnVucy5cbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRFeHRlcm5hbFJlZHVjZXJzKFxuICBnbG9iYWw6IFJlY29yZDxzdHJpbmcsIGFueT4gPSBnbG9iYWxUaGlzLFxuICBvcHM6IFByb21pc2U8dm9pZD5bXSxcbiAgcnVuSWQ6IHN0cmluZyxcbiAgY3J5cHRvS2V5OiBFbmNyeXB0aW9uS2V5UGFyYW0sXG4gIGZyYW1lZEJ5dGVTdHJlYW1zID0gZmFsc2Vcbik6IFBhcnRpYWw8UmVkdWNlcnM+IHtcbiAgcmV0dXJuIHtcbiAgICAuLi5nZXRBbGxCYXNlUmVkdWNlcnMoZ2xvYmFsKSxcblxuICAgIFJlYWRhYmxlU3RyZWFtOiAodmFsdWUpID0+IHtcbiAgICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgZ2xvYmFsLlJlYWRhYmxlU3RyZWFtKSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgICAvLyBTdHJlYW0gbXVzdCBub3QgYmUgbG9ja2VkIHdoZW4gcGFzc2luZyBhY3Jvc3MgZXhlY3V0aW9uIGJvdW5kYXJ5XG4gICAgICBpZiAodmFsdWUubG9ja2VkKSB7XG4gICAgICAgIHRocm93IG5ldyBTZXJpYWxpemF0aW9uRXJyb3IoXG4gICAgICAgICAgJ1JlYWRhYmxlU3RyZWFtIGlzIGxvY2tlZCBhbmQgY2Fubm90IGJlIHBhc3NlZCBhY3Jvc3MgYSB3b3JrZmxvdyBib3VuZGFyeS4nLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGhpbnQ6ICdQYXNzIHRoZSBzdHJlYW0gYmVmb3JlIGNhbGxpbmcgLmdldFJlYWRlcigpIC8gLnBpcGVUaHJvdWdoKCkgLyAucGlwZVRvKCksIG9yIHRlZSBpdCB3aXRoIC50ZWUoKSBhbmQgcGFzcyBvbmUgb2YgdGhlIGJyYW5jaGVzLicsXG4gICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBzdHJlYW1JZCA9ICgoZ2xvYmFsIGFzIGFueSlbU1RBQkxFX1VMSURdIHx8IGRlZmF1bHRVbGlkKSgpO1xuICAgICAgY29uc3QgbmFtZSA9IGBzdHJtXyR7c3RyZWFtSWR9YDtcbiAgICAgIGNvbnN0IHR5cGUgPSBnZXRTdHJlYW1UeXBlKHZhbHVlKTtcblxuICAgICAgY29uc3Qgd3JpdGFibGUgPSBuZXcgV29ya2Zsb3dTZXJ2ZXJXcml0YWJsZVN0cmVhbShydW5JZCwgbmFtZSk7XG4gICAgICBpZiAodHlwZSA9PT0gJ2J5dGVzJykge1xuICAgICAgICBpZiAoZnJhbWVkQnl0ZVN0cmVhbXMpIHtcbiAgICAgICAgICBvcHMucHVzaCh2YWx1ZS5waXBlVGhyb3VnaChnZXRCeXRlRnJhbWluZ1N0cmVhbSgpKS5waXBlVG8od3JpdGFibGUpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBvcHMucHVzaCh2YWx1ZS5waXBlVG8od3JpdGFibGUpKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb3BzLnB1c2goXG4gICAgICAgICAgdmFsdWVcbiAgICAgICAgICAgIC5waXBlVGhyb3VnaChcbiAgICAgICAgICAgICAgZ2V0U2VyaWFsaXplU3RyZWFtKFxuICAgICAgICAgICAgICAgIGdldEV4dGVybmFsUmVkdWNlcnMoXG4gICAgICAgICAgICAgICAgICBnbG9iYWwsXG4gICAgICAgICAgICAgICAgICBvcHMsXG4gICAgICAgICAgICAgICAgICBydW5JZCxcbiAgICAgICAgICAgICAgICAgIGNyeXB0b0tleSxcbiAgICAgICAgICAgICAgICAgIGZyYW1lZEJ5dGVTdHJlYW1zXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBjcnlwdG9LZXlcbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgLnBpcGVUbyh3cml0YWJsZSlcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgczogU2VyaWFsaXphYmxlU3BlY2lhbFsnUmVhZGFibGVTdHJlYW0nXSA9IHsgbmFtZSB9O1xuICAgICAgaWYgKHR5cGUpIHMudHlwZSA9IHR5cGU7XG4gICAgICBpZiAodHlwZSA9PT0gJ2J5dGVzJyAmJiBmcmFtZWRCeXRlU3RyZWFtcykgcy5mcmFtaW5nID0gJ2ZyYW1lZC12MSc7XG4gICAgICByZXR1cm4gcztcbiAgICB9LFxuXG4gICAgV3JpdGFibGVTdHJlYW06ICh2YWx1ZSkgPT4ge1xuICAgICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBnbG9iYWwuV3JpdGFibGVTdHJlYW0pKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgIC8vIEZhc3QgcGF0aDogd2hlbiB0aGUgd3JpdGFibGUgaXMgYWxyZWFkeSBiYWNrZWQgYnkgYSB3b3JrZmxvd1xuICAgICAgLy8gc2VydmVyIHN0cmVhbSAoZS5nLiBpdCBjYW1lIGZyb20gYSBzdGVwLWNvbnRleHQgYGdldFdyaXRhYmxlKClgXG4gICAgICAvLyBvciB3YXMgaHlkcmF0ZWQgZnJvbSBhIHdvcmtmbG93IGlucHV0IGJ5IGBnZXRTdGVwUmV2aXZlcnNgKSxcbiAgICAgIC8vIGZvcndhcmQgaXRzIHVuZGVybHlpbmcgYChydW5JZCwgbmFtZSlgIHRvIHRoZSByZWNlaXZpbmcgcnVuLlxuICAgICAgLy8gVGhlIHJlY2VpdmluZyBydW4ncyBzdGVwLXNpZGUgcmV2aXZlciBvcGVucyBhIHNlcnZlciB3cml0YWJsZVxuICAgICAgLy8gYWdhaW5zdCB0aGUgb3JpZ2luYWwgYChydW5JZCwgbmFtZSlgIGFuZCByZXNvbHZlcyB0aGF0IHJ1bidzXG4gICAgICAvLyBlbmNyeXB0aW9uIGtleSBkaXJlY3RseSwgc28gd3JpdGVzIGxhbmQgb24gdGhlIG9yaWdpbmFsIHN0cmVhbVxuICAgICAgLy8gZm9yIHRoZSBmdWxsIGxpZmV0aW1lIG9mIHRoZSByZWNlaXZpbmcgcnVuIOKAlCBubyBpbi1wcm9jZXNzXG4gICAgICAvLyBicmlkZ2UgdGllZCB0byB0aGUgZGVoeWRyYXRpbmcgc3RlcCdzIGxpZmV0aW1lLlxuICAgICAgY29uc3QgZXhpc3RpbmdOYW1lID0gKHZhbHVlIGFzIGFueSlbU1RSRUFNX05BTUVfU1lNQk9MXTtcbiAgICAgIGNvbnN0IGV4aXN0aW5nUnVuSWQgPSAodmFsdWUgYXMgYW55KVtTVFJFQU1fU0VSVkVSX1JVTl9JRF9TWU1CT0xdO1xuICAgICAgaWYgKFxuICAgICAgICB0eXBlb2YgZXhpc3RpbmdOYW1lID09PSAnc3RyaW5nJyAmJlxuICAgICAgICB0eXBlb2YgZXhpc3RpbmdSdW5JZCA9PT0gJ3N0cmluZydcbiAgICAgICkge1xuICAgICAgICBjb25zdCBkZXNjcmlwdG9yOiBTZXJpYWxpemFibGVTcGVjaWFsWydXcml0YWJsZVN0cmVhbSddID0ge1xuICAgICAgICAgIG5hbWU6IGV4aXN0aW5nTmFtZSxcbiAgICAgICAgICBydW5JZDogZXhpc3RpbmdSdW5JZCxcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgZXhpc3RpbmdEZXBsb3ltZW50SWQgPSAodmFsdWUgYXMgYW55KVtcbiAgICAgICAgICBTVFJFQU1fU0VSVkVSX0RFUExPWU1FTlRfSURfU1lNQk9MXG4gICAgICAgIF07XG4gICAgICAgIGlmICh0eXBlb2YgZXhpc3RpbmdEZXBsb3ltZW50SWQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgZGVzY3JpcHRvci5kZXBsb3ltZW50SWQgPSBleGlzdGluZ0RlcGxveW1lbnRJZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGVzY3JpcHRvcjtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc3RyZWFtSWQgPSAoKGdsb2JhbCBhcyBhbnkpW1NUQUJMRV9VTElEXSB8fCBkZWZhdWx0VWxpZCkoKTtcbiAgICAgIGNvbnN0IG5hbWUgPSBgc3RybV8ke3N0cmVhbUlkfWA7XG4gICAgICBjb25zdCByZWFkYWJsZSA9IG5ldyBXb3JrZmxvd1NlcnZlclJlYWRhYmxlU3RyZWFtKHJ1bklkLCBuYW1lKTtcbiAgICAgIG9wcy5wdXNoKHJlYWRhYmxlLnBpcGVUbyh2YWx1ZSkpO1xuXG4gICAgICByZXR1cm4geyBuYW1lIH07XG4gICAgfSxcblxuICAgIEFib3J0Q29udHJvbGxlcjogKHZhbHVlKSA9PiB7XG4gICAgICBpZiAoXG4gICAgICAgICFnbG9iYWwuQWJvcnRDb250cm9sbGVyIHx8XG4gICAgICAgIHR5cGVvZiBnbG9iYWwuQWJvcnRDb250cm9sbGVyICE9PSAnZnVuY3Rpb24nIHx8XG4gICAgICAgICEodmFsdWUgaW5zdGFuY2VvZiBnbG9iYWwuQWJvcnRDb250cm9sbGVyKVxuICAgICAgKVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICByZXR1cm4gcmVkdWNlQWJvcnRXaXRoTGlzdGVuZXIoXG4gICAgICAgIHZhbHVlLnNpZ25hbCxcbiAgICAgICAgdmFsdWUsXG4gICAgICAgIGdsb2JhbCxcbiAgICAgICAgb3BzLFxuICAgICAgICBydW5JZCxcbiAgICAgICAgY3J5cHRvS2V5XG4gICAgICApO1xuICAgIH0sXG5cbiAgICBBYm9ydFNpZ25hbDogKHZhbHVlKSA9PiB7XG4gICAgICBpZiAoXG4gICAgICAgICFnbG9iYWwuQWJvcnRTaWduYWwgfHxcbiAgICAgICAgdHlwZW9mIGdsb2JhbC5BYm9ydFNpZ25hbCAhPT0gJ2Z1bmN0aW9uJyB8fFxuICAgICAgICAhKHZhbHVlIGluc3RhbmNlb2YgZ2xvYmFsLkFib3J0U2lnbmFsKVxuICAgICAgKVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICByZXR1cm4gcmVkdWNlQWJvcnRXaXRoTGlzdGVuZXIoXG4gICAgICAgIHZhbHVlLFxuICAgICAgICB2YWx1ZSxcbiAgICAgICAgZ2xvYmFsLFxuICAgICAgICBvcHMsXG4gICAgICAgIHJ1bklkLFxuICAgICAgICBjcnlwdG9LZXlcbiAgICAgICk7XG4gICAgfSxcbiAgfTtcbn1cblxuLyoqXG4gKiBSZWR1Y2VycyBmb3Igc2VyaWFsaXphdGlvbiBib3VuZGFyeSBmcm9tIHdpdGhpbiB0aGUgd29ya2Zsb3cgZXhlY3V0aW9uXG4gKiBlbnZpcm9ubWVudCwgcGFzc2luZyByZXR1cm4gdmFsdWUgdG8gdGhlIGNsaWVudCBzaWRlIGFuZCBpbnRvIHN0ZXAgYXJndW1lbnRzLlxuICpcbiAqIEBwYXJhbSBnbG9iYWxcbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRXb3JrZmxvd1JlZHVjZXJzKFxuICBnbG9iYWw6IFJlY29yZDxzdHJpbmcsIGFueT4gPSBnbG9iYWxUaGlzXG4pOiBQYXJ0aWFsPFJlZHVjZXJzPiB7XG4gIHJldHVybiB7XG4gICAgLi4uZ2V0QWxsQmFzZVJlZHVjZXJzKGdsb2JhbCksXG5cbiAgICAvLyBSZWFkYWJsZS9Xcml0YWJsZSBzdHJlYW1zIGZyb20gd2l0aGluIHRoZSB3b3JrZmxvdyBleGVjdXRpb24gZW52aXJvbm1lbnRcbiAgICAvLyBhcmUgc2ltcGx5IFwiaGFuZGxlc1wiIHRoYXQgY2FuIGJlIHBhc3NlZCBhcm91bmQgdG8gb3RoZXIgc3RlcHMuXG4gICAgUmVhZGFibGVTdHJlYW06ICh2YWx1ZSkgPT4ge1xuICAgICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBnbG9iYWwuUmVhZGFibGVTdHJlYW0pKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgIC8vIENoZWNrIGlmIHRoaXMgaXMgYSBmYWtlIHN0cmVhbSBzdG9yaW5nIEJvZHlJbml0IGZyb20gUmVxdWVzdC9SZXNwb25zZSBjb25zdHJ1Y3RvclxuICAgICAgY29uc3QgYm9keUluaXQgPSB2YWx1ZVtCT0RZX0lOSVRfU1lNQk9MXTtcbiAgICAgIGlmIChib2R5SW5pdCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIC8vIFRoaXMgaXMgYSBmYWtlIHN0cmVhbSAtIHNlcmlhbGl6ZSB0aGUgQm9keUluaXQgZGlyZWN0bHlcbiAgICAgICAgLy8gZGV2YWx1ZSB3aWxsIGhhbmRsZSBzZXJpYWxpemluZyBzdHJpbmdzLCBVaW50OEFycmF5LCBldGMuXG4gICAgICAgIHJldHVybiB7IGJvZHlJbml0IH07XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG5hbWUgPSB2YWx1ZVtTVFJFQU1fTkFNRV9TWU1CT0xdO1xuICAgICAgaWYgKCFuYW1lKSB7XG4gICAgICAgIHRocm93IG5ldyBXb3JrZmxvd1J1bnRpbWVFcnJvcignUmVhZGFibGVTdHJlYW0gYG5hbWVgIGlzIG5vdCBzZXQnKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHM6IFNlcmlhbGl6YWJsZVNwZWNpYWxbJ1JlYWRhYmxlU3RyZWFtJ10gPSB7IG5hbWUgfTtcbiAgICAgIGNvbnN0IHR5cGUgPSB2YWx1ZVtTVFJFQU1fVFlQRV9TWU1CT0xdO1xuICAgICAgaWYgKHR5cGUpIHMudHlwZSA9IHR5cGU7XG4gICAgICBjb25zdCBmcmFtaW5nOiBCeXRlU3RyZWFtRnJhbWluZyB8IHVuZGVmaW5lZCA9XG4gICAgICAgIHZhbHVlW1NUUkVBTV9GUkFNSU5HX1NZTUJPTF07XG4gICAgICBpZiAoZnJhbWluZykgcy5mcmFtaW5nID0gZnJhbWluZztcbiAgICAgIHJldHVybiBzO1xuICAgIH0sXG4gICAgV3JpdGFibGVTdHJlYW06ICh2YWx1ZSkgPT4ge1xuICAgICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBnbG9iYWwuV3JpdGFibGVTdHJlYW0pKSByZXR1cm4gZmFsc2U7XG4gICAgICBjb25zdCBuYW1lID0gdmFsdWVbU1RSRUFNX05BTUVfU1lNQk9MXTtcbiAgICAgIGlmICghbmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgV29ya2Zsb3dSdW50aW1lRXJyb3IoJ1dyaXRhYmxlU3RyZWFtIGBuYW1lYCBpcyBub3Qgc2V0Jyk7XG4gICAgICB9XG4gICAgICBjb25zdCBzOiBTZXJpYWxpemFibGVTcGVjaWFsWydXcml0YWJsZVN0cmVhbSddID0geyBuYW1lIH07XG4gICAgICAvLyBXaGVuIHRoZSBoYW5kbGUgd2FzIGZvcndhcmRlZCBmcm9tIGFub3RoZXIgcnVuIChwYXJlbnQg4oaSIGNoaWxkXG4gICAgICAvLyB2aWEgYHN0YXJ0KClgKSwgcHJlc2VydmUgdGhlIGZvcmVpZ24gcnVuSWQgc28gdGhlIHN0ZXAtc2lkZVxuICAgICAgLy8gcmV2aXZlciBvcGVucyB0aGUgd3JpdGFibGUgYWdhaW5zdCB0aGUgb3JpZ2luYWwgc3RyZWFtLlxuICAgICAgY29uc3QgZm9yZWlnblJ1bklkID0gdmFsdWVbU1RSRUFNX1NFUlZFUl9SVU5fSURfU1lNQk9MXTtcbiAgICAgIGlmICh0eXBlb2YgZm9yZWlnblJ1bklkID09PSAnc3RyaW5nJykgcy5ydW5JZCA9IGZvcmVpZ25SdW5JZDtcbiAgICAgIGNvbnN0IGZvcmVpZ25EZXBsb3ltZW50SWQgPSB2YWx1ZVtTVFJFQU1fU0VSVkVSX0RFUExPWU1FTlRfSURfU1lNQk9MXTtcbiAgICAgIGlmICh0eXBlb2YgZm9yZWlnbkRlcGxveW1lbnRJZCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgcy5kZXBsb3ltZW50SWQgPSBmb3JlaWduRGVwbG95bWVudElkO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHM7XG4gICAgfSxcblxuICAgIC8vIEFib3J0Q29udHJvbGxlci9BYm9ydFNpZ25hbCBpbiB3b3JrZmxvdyBjb250ZXh0IOKAlCBqdXN0IHJlYWQgc3ltYm9scyAoaGFuZGxlcykuXG4gICAgLy8gSW4gdGhlIHdvcmtmbG93IFZNLCBnbG9iYWwuQWJvcnRDb250cm9sbGVyIGlzIGEgY2xhc3MgYnV0IGdsb2JhbC5BYm9ydFNpZ25hbFxuICAgIC8vIGlzIGEgcGxhaW4gb2JqZWN0IChub3QgYSBjbGFzcyksIHNvIGluc3RhbmNlb2YgY2hlY2tzIHdvbid0IHdvcmsgZm9yIHNpZ25hbHMuXG4gICAgLy8gRGV0ZWN0IGluc3RhbmNlcyBieSB0aGUgcHJlc2VuY2Ugb2YgdGhlIEFCT1JUX1NUUkVBTV9OQU1FIHN5bWJvbCBpbnN0ZWFkLlxuICAgIEFib3J0Q29udHJvbGxlcjogKHZhbHVlKSA9PiB7XG4gICAgICBpZiAoIXZhbHVlIHx8ICF2YWx1ZS5zaWduYWwpIHJldHVybiBmYWxzZTtcbiAgICAgIGNvbnN0IGhvbGRlciA9IHZhbHVlIGFzIEFib3J0Q29udHJvbGxlciAmIEFib3J0SG9sZGVyO1xuICAgICAgY29uc3QgaGFzQWJvcnRTeW1ib2wgPVxuICAgICAgICBob2xkZXJbQUJPUlRfU1RSRUFNX05BTUVdID8/IGhvbGRlci5zaWduYWw/LltBQk9SVF9TVFJFQU1fTkFNRV07XG4gICAgICBjb25zdCBpc05hdGl2ZUFib3J0Q29udHJvbGxlciA9XG4gICAgICAgIGdsb2JhbC5BYm9ydENvbnRyb2xsZXIgJiZcbiAgICAgICAgdHlwZW9mIGdsb2JhbC5BYm9ydENvbnRyb2xsZXIgPT09ICdmdW5jdGlvbicgJiZcbiAgICAgICAgdmFsdWUgaW5zdGFuY2VvZiBnbG9iYWwuQWJvcnRDb250cm9sbGVyO1xuICAgICAgaWYgKCFoYXNBYm9ydFN5bWJvbCAmJiAhaXNOYXRpdmVBYm9ydENvbnRyb2xsZXIpIHJldHVybiBmYWxzZTtcbiAgICAgIHJldHVybiByZWR1Y2VBYm9ydEJ5U3ltYm9sKHZhbHVlLnNpZ25hbCwgaG9sZGVyKTtcbiAgICB9LFxuICAgIEFib3J0U2lnbmFsOiAodmFsdWUpID0+IHtcbiAgICAgIGNvbnN0IHNpZ25hbCA9IHZhbHVlIGFzIChBYm9ydFNpZ25hbCAmIEFib3J0SW50ZXJuYWxzKSB8IHVuZGVmaW5lZDtcbiAgICAgIGNvbnN0IGhhc0Fib3J0U3ltYm9sID0gc2lnbmFsPy5bQUJPUlRfU1RSRUFNX05BTUVdO1xuICAgICAgY29uc3QgaXNOYXRpdmVBYm9ydFNpZ25hbCA9XG4gICAgICAgIGdsb2JhbC5BYm9ydFNpZ25hbCAmJlxuICAgICAgICB0eXBlb2YgZ2xvYmFsLkFib3J0U2lnbmFsID09PSAnZnVuY3Rpb24nICYmXG4gICAgICAgIHZhbHVlIGluc3RhbmNlb2YgZ2xvYmFsLkFib3J0U2lnbmFsO1xuICAgICAgaWYgKCFoYXNBYm9ydFN5bWJvbCAmJiAhaXNOYXRpdmVBYm9ydFNpZ25hbCkgcmV0dXJuIGZhbHNlO1xuICAgICAgcmV0dXJuIHJlZHVjZUFib3J0QnlTeW1ib2wodmFsdWUsIHZhbHVlIGFzIEFib3J0SG9sZGVyKTtcbiAgICB9LFxuICB9O1xufVxuXG4vKipcbiAqIFJlZHVjZXJzIGZvciBzZXJpYWxpemF0aW9uIGJvdW5kYXJ5IGZyb20gd2l0aGluIHRoZSBzdGVwIGV4ZWN1dGlvblxuICogZW52aXJvbm1lbnQsIHBhc3NpbmcgcmV0dXJuIHZhbHVlIHRvIHRoZSB3b3JrZmxvdyBoYW5kbGVyLlxuICpcbiAqIEBwYXJhbSBnbG9iYWxcbiAqIEBwYXJhbSBvcHNcbiAqIEBwYXJhbSBydW5JZFxuICogQHJldHVybnNcbiAqL1xuZnVuY3Rpb24gZ2V0U3RlcFJlZHVjZXJzKFxuICBnbG9iYWw6IFJlY29yZDxzdHJpbmcsIGFueT4gPSBnbG9iYWxUaGlzLFxuICBvcHM6IFByb21pc2U8dm9pZD5bXSxcbiAgcnVuSWQ6IHN0cmluZyxcbiAgY3J5cHRvS2V5OiBFbmNyeXB0aW9uS2V5UGFyYW0sXG4gIGZyYW1lZEJ5dGVTdHJlYW1zID0gZmFsc2Vcbik6IFBhcnRpYWw8UmVkdWNlcnM+IHtcbiAgcmV0dXJuIHtcbiAgICAuLi5nZXRBbGxCYXNlUmVkdWNlcnMoZ2xvYmFsKSxcblxuICAgIFJlYWRhYmxlU3RyZWFtOiAodmFsdWUpID0+IHtcbiAgICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgZ2xvYmFsLlJlYWRhYmxlU3RyZWFtKSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgICAvLyBTdHJlYW0gbXVzdCBub3QgYmUgbG9ja2VkIHdoZW4gcGFzc2luZyBhY3Jvc3MgZXhlY3V0aW9uIGJvdW5kYXJ5XG4gICAgICBpZiAodmFsdWUubG9ja2VkKSB7XG4gICAgICAgIHRocm93IG5ldyBTZXJpYWxpemF0aW9uRXJyb3IoXG4gICAgICAgICAgJ1JlYWRhYmxlU3RyZWFtIGlzIGxvY2tlZCBhbmQgY2Fubm90IGJlIHBhc3NlZCBhY3Jvc3MgYSB3b3JrZmxvdyBib3VuZGFyeS4nLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGhpbnQ6ICdQYXNzIHRoZSBzdHJlYW0gYmVmb3JlIGNhbGxpbmcgLmdldFJlYWRlcigpIC8gLnBpcGVUaHJvdWdoKCkgLyAucGlwZVRvKCksIG9yIHRlZSBpdCB3aXRoIC50ZWUoKSBhbmQgcGFzcyBvbmUgb2YgdGhlIGJyYW5jaGVzLicsXG4gICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICAvLyBDaGVjayBpZiB0aGUgc3RyZWFtIGFscmVhZHkgaGFzIHRoZSBuYW1lIHN5bWJvbCBzZXQsIGluIHdoaWNoIGNhc2VcbiAgICAgIC8vIGl0J3MgYWxyZWFkeSBiZWluZyBzdW5rIHRvIHRoZSBzZXJ2ZXIgYW5kIHdlIGNhbiBqdXN0IHJldHVybiB0aGVcbiAgICAgIC8vIG5hbWUgYW5kIHR5cGUuXG4gICAgICBsZXQgbmFtZSA9IHZhbHVlW1NUUkVBTV9OQU1FX1NZTUJPTF07XG4gICAgICBsZXQgdHlwZSA9IHZhbHVlW1NUUkVBTV9UWVBFX1NZTUJPTF07XG4gICAgICAvLyBUaGUgZnJhbWluZyBzeW1ib2wgaXMgc2V0IHdoZW4gYSB3b3JrZmxvdyBWTSByZXZpdmVzIGEgc3RyZWFtXG4gICAgICAvLyBoYW5kbGUgZnJvbSBhIHByZXZpb3VzIHN0ZXAgKHNlZSBgZ2V0V29ya2Zsb3dSZXZpdmVyc2ApLiBXaGVuXG4gICAgICAvLyBwcmVzZW50IHdlIG11c3QgcHJvcGFnYXRlIHRoZSBzYW1lIGZyYW1pbmcgY2hvaWNlIG9uIHRoZSB3YXlcbiAgICAgIC8vIGJhY2sgb3V0LCBzaW5jZSB0aGUgYnl0ZXMgYWxyZWFkeSBvbiB0aGUgc2VydmVyJ3Mgc3RyZWFtIGFyZSBpblxuICAgICAgLy8gdGhhdCBmb3JtYXQg4oCUIHN3aXRjaGluZyBmb3JtYXQgbWlkLXN0cmVhbSB3b3VsZCBjb3JydXB0IHRoZW0uXG4gICAgICBsZXQgZnJhbWluZzogQnl0ZVN0cmVhbUZyYW1pbmcgfCB1bmRlZmluZWQgPSB2YWx1ZVtTVFJFQU1fRlJBTUlOR19TWU1CT0xdO1xuXG4gICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgY29uc3Qgc3RyZWFtSWQgPSAoKGdsb2JhbCBhcyBhbnkpW1NUQUJMRV9VTElEXSB8fCBkZWZhdWx0VWxpZCkoKTtcbiAgICAgICAgbmFtZSA9IGBzdHJtXyR7c3RyZWFtSWR9YDtcbiAgICAgICAgdHlwZSA9IGdldFN0cmVhbVR5cGUodmFsdWUpO1xuICAgICAgICBmcmFtaW5nID0gdHlwZSA9PT0gJ2J5dGVzJyAmJiBmcmFtZWRCeXRlU3RyZWFtcyA/ICdmcmFtZWQtdjEnIDogZnJhbWluZztcblxuICAgICAgICBjb25zdCB3cml0YWJsZSA9IG5ldyBXb3JrZmxvd1NlcnZlcldyaXRhYmxlU3RyZWFtKHJ1bklkLCBuYW1lKTtcbiAgICAgICAgaWYgKHR5cGUgPT09ICdieXRlcycpIHtcbiAgICAgICAgICBpZiAoZnJhbWluZyA9PT0gJ2ZyYW1lZC12MScpIHtcbiAgICAgICAgICAgIG9wcy5wdXNoKFxuICAgICAgICAgICAgICB2YWx1ZS5waXBlVGhyb3VnaChnZXRCeXRlRnJhbWluZ1N0cmVhbSgpKS5waXBlVG8od3JpdGFibGUpXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBvcHMucHVzaCh2YWx1ZS5waXBlVG8od3JpdGFibGUpKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgb3BzLnB1c2goXG4gICAgICAgICAgICB2YWx1ZVxuICAgICAgICAgICAgICAucGlwZVRocm91Z2goXG4gICAgICAgICAgICAgICAgZ2V0U2VyaWFsaXplU3RyZWFtKFxuICAgICAgICAgICAgICAgICAgZ2V0U3RlcFJlZHVjZXJzKFxuICAgICAgICAgICAgICAgICAgICBnbG9iYWwsXG4gICAgICAgICAgICAgICAgICAgIG9wcyxcbiAgICAgICAgICAgICAgICAgICAgcnVuSWQsXG4gICAgICAgICAgICAgICAgICAgIGNyeXB0b0tleSxcbiAgICAgICAgICAgICAgICAgICAgZnJhbWVkQnl0ZVN0cmVhbXNcbiAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICBjcnlwdG9LZXlcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgLnBpcGVUbyh3cml0YWJsZSlcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHM6IFNlcmlhbGl6YWJsZVNwZWNpYWxbJ1JlYWRhYmxlU3RyZWFtJ10gPSB7IG5hbWUgfTtcbiAgICAgIGlmICh0eXBlKSBzLnR5cGUgPSB0eXBlO1xuICAgICAgaWYgKGZyYW1pbmcpIHMuZnJhbWluZyA9IGZyYW1pbmc7XG4gICAgICByZXR1cm4gcztcbiAgICB9LFxuXG4gICAgV3JpdGFibGVTdHJlYW06ICh2YWx1ZSkgPT4ge1xuICAgICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBnbG9iYWwuV3JpdGFibGVTdHJlYW0pKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgIGxldCBuYW1lID0gdmFsdWVbU1RSRUFNX05BTUVfU1lNQk9MXTtcbiAgICAgIGNvbnN0IGZvcmVpZ25SdW5JZCA9ICh2YWx1ZSBhcyBhbnkpW1NUUkVBTV9TRVJWRVJfUlVOX0lEX1NZTUJPTF07XG4gICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgY29uc3Qgc3RyZWFtSWQgPSAoKGdsb2JhbCBhcyBhbnkpW1NUQUJMRV9VTElEXSB8fCBkZWZhdWx0VWxpZCkoKTtcbiAgICAgICAgbmFtZSA9IGBzdHJtXyR7c3RyZWFtSWR9YDtcbiAgICAgICAgb3BzLnB1c2goXG4gICAgICAgICAgbmV3IFdvcmtmbG93U2VydmVyUmVhZGFibGVTdHJlYW0ocnVuSWQsIG5hbWUpXG4gICAgICAgICAgICAucGlwZVRocm91Z2goXG4gICAgICAgICAgICAgIGdldERlc2VyaWFsaXplU3RyZWFtKFxuICAgICAgICAgICAgICAgIGdldFN0ZXBSZXZpdmVycyhnbG9iYWwsIG9wcywgcnVuSWQsIGNyeXB0b0tleSksXG4gICAgICAgICAgICAgICAgY3J5cHRvS2V5XG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgIClcbiAgICAgICAgICAgIC5waXBlVG8odmFsdWUpXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHM6IFNlcmlhbGl6YWJsZVNwZWNpYWxbJ1dyaXRhYmxlU3RyZWFtJ10gPSB7IG5hbWUgfTtcbiAgICAgIGlmICh0eXBlb2YgZm9yZWlnblJ1bklkID09PSAnc3RyaW5nJykgcy5ydW5JZCA9IGZvcmVpZ25SdW5JZDtcbiAgICAgIGNvbnN0IGZvcmVpZ25EZXBsb3ltZW50SWQgPSAodmFsdWUgYXMgYW55KVtcbiAgICAgICAgU1RSRUFNX1NFUlZFUl9ERVBMT1lNRU5UX0lEX1NZTUJPTFxuICAgICAgXTtcbiAgICAgIGlmICh0eXBlb2YgZm9yZWlnbkRlcGxveW1lbnRJZCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgcy5kZXBsb3ltZW50SWQgPSBmb3JlaWduRGVwbG95bWVudElkO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHM7XG4gICAgfSxcblxuICAgIEFib3J0Q29udHJvbGxlcjogKHZhbHVlKSA9PiB7XG4gICAgICBpZiAoXG4gICAgICAgICFnbG9iYWwuQWJvcnRDb250cm9sbGVyIHx8XG4gICAgICAgIHR5cGVvZiBnbG9iYWwuQWJvcnRDb250cm9sbGVyICE9PSAnZnVuY3Rpb24nIHx8XG4gICAgICAgICEodmFsdWUgaW5zdGFuY2VvZiBnbG9iYWwuQWJvcnRDb250cm9sbGVyKVxuICAgICAgKVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICByZXR1cm4gcmVkdWNlQWJvcnRXaXRoTGlzdGVuZXIoXG4gICAgICAgIHZhbHVlLnNpZ25hbCxcbiAgICAgICAgdmFsdWUsXG4gICAgICAgIGdsb2JhbCxcbiAgICAgICAgb3BzLFxuICAgICAgICBydW5JZCxcbiAgICAgICAgY3J5cHRvS2V5XG4gICAgICApO1xuICAgIH0sXG5cbiAgICBBYm9ydFNpZ25hbDogKHZhbHVlKSA9PiB7XG4gICAgICBpZiAoXG4gICAgICAgICFnbG9iYWwuQWJvcnRTaWduYWwgfHxcbiAgICAgICAgdHlwZW9mIGdsb2JhbC5BYm9ydFNpZ25hbCAhPT0gJ2Z1bmN0aW9uJyB8fFxuICAgICAgICAhKHZhbHVlIGluc3RhbmNlb2YgZ2xvYmFsLkFib3J0U2lnbmFsKVxuICAgICAgKVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICByZXR1cm4gcmVkdWNlQWJvcnRXaXRoTGlzdGVuZXIoXG4gICAgICAgIHZhbHVlLFxuICAgICAgICB2YWx1ZSxcbiAgICAgICAgZ2xvYmFsLFxuICAgICAgICBvcHMsXG4gICAgICAgIHJ1bklkLFxuICAgICAgICBjcnlwdG9LZXlcbiAgICAgICk7XG4gICAgfSxcbiAgfTtcbn1cblxuLyoqXG4gKiBDYW5jZWwgZGFuZ2xpbmcgYWJvcnQtc3RyZWFtIHJlYWRlcnMgb24gYW55IEFib3J0Q29udHJvbGxlciBpbnN0YW5jZXMgZm91bmRcbiAqIGluIHRoZSBoeWRyYXRlZCBzdGVwIGFyZ3VtZW50cy4gQ2FsbGVkIGFmdGVyIHRoZSBzdGVwIGZ1bmN0aW9uIHJldHVybnNcbiAqIChzdWNjZXNzIG9yIGZhaWx1cmUpIHRvIHByZXZlbnQgcmVhZGVyIHByb21pc2VzIGZyb20ga2VlcGluZyB0aGUgc2VydmVybGVzc1xuICogZnVuY3Rpb24gYWxpdmUgaW5kZWZpbml0ZWx5LlxuICovXG5leHBvcnQgZnVuY3Rpb24gY2FuY2VsQWJvcnRSZWFkZXJzKC4uLnZhbHVlczogdW5rbm93bltdKTogdm9pZCB7XG4gIGNvbnN0IHZpc2l0ZWQgPSBuZXcgV2Vha1NldCgpO1xuICBmdW5jdGlvbiBjYW5jZWxJZlByZXNlbnQodmFsOiBBYm9ydEludGVybmFscyk6IHZvaWQge1xuICAgIGNvbnN0IGNhbmNlbCA9IHZhbFtBQk9SVF9SRUFERVJfQ0FOQ0VMXTtcbiAgICBpZiAoY2FuY2VsICYmICFjYW5jZWwuc2lnbmFsLmFib3J0ZWQpIHtcbiAgICAgIGNhbmNlbC5hYm9ydCgpO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiB3YWxrKHZhbDogdW5rbm93bik6IHZvaWQge1xuICAgIGlmICh2YWwgPT0gbnVsbCB8fCB0eXBlb2YgdmFsICE9PSAnb2JqZWN0JykgcmV0dXJuO1xuICAgIGlmICh2aXNpdGVkLmhhcyh2YWwgYXMgb2JqZWN0KSkgcmV0dXJuO1xuICAgIHZpc2l0ZWQuYWRkKHZhbCBhcyBvYmplY3QpO1xuICAgIGlmICh2YWwgaW5zdGFuY2VvZiBBYm9ydENvbnRyb2xsZXIpIHtcbiAgICAgIGNhbmNlbElmUHJlc2VudCh2YWwgYXMgQWJvcnRDb250cm9sbGVyICYgQWJvcnRJbnRlcm5hbHMpO1xuICAgICAgY2FuY2VsSWZQcmVzZW50KHZhbC5zaWduYWwgYXMgQWJvcnRTaWduYWwgJiBBYm9ydEludGVybmFscyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICh2YWwgaW5zdGFuY2VvZiBBYm9ydFNpZ25hbCkge1xuICAgICAgY2FuY2VsSWZQcmVzZW50KHZhbCBhcyBBYm9ydFNpZ25hbCAmIEFib3J0SW50ZXJuYWxzKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKEFycmF5LmlzQXJyYXkodmFsKSkge1xuICAgICAgZm9yIChjb25zdCBpdGVtIG9mIHZhbCkgd2FsayhpdGVtKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHZhbCBpbnN0YW5jZW9mIE1hcCkge1xuICAgICAgZm9yIChjb25zdCB2IG9mIHZhbC52YWx1ZXMoKSkgd2Fsayh2KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHZhbCBpbnN0YW5jZW9mIFNldCkge1xuICAgICAgZm9yIChjb25zdCB2IG9mIHZhbCkgd2Fsayh2KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gUmVxdWVzdC9SZXNwb25zZSBleHBvc2UgYHNpZ25hbGAvYGJvZHlgIGFzIHByb3RvdHlwZSBnZXR0ZXJzLCBzb1xuICAgIC8vIE9iamVjdC52YWx1ZXMoKSB3b24ndCBmaW5kIHRoZW0uIERlc2NlbmQgZXhwbGljaXRseS5cbiAgICBpZiAodHlwZW9mIFJlcXVlc3QgIT09ICd1bmRlZmluZWQnICYmIHZhbCBpbnN0YW5jZW9mIFJlcXVlc3QpIHtcbiAgICAgIHdhbGsodmFsLnNpZ25hbCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGZvciAoY29uc3QgdiBvZiBPYmplY3QudmFsdWVzKHZhbCBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikpIHdhbGsodik7XG4gIH1cbiAgZm9yIChjb25zdCB2IG9mIHZhbHVlcykgd2Fsayh2KTtcbn1cblxuLyoqXG4gKiBTZXRzIHVwIGEgc3RyZWFtIHJlYWRlciBvbiB0aGUgY29udHJvbGxlciB0aGF0IGxpc3RlbnMgZm9yIGFuIGFib3J0IHBhY2tldC5cbiAqIFJldHVybnMgdGhlIHJlYWRlckNhbmNlbCBjb250cm9sbGVyIHNvIGl0IGNhbiBiZSBzdG9yZWQgb24gYm90aCB0aGVcbiAqIGNvbnRyb2xsZXIgYW5kIHNpZ25hbCBmb3IgY2xlYW51cCBieSBjYW5jZWxBYm9ydFJlYWRlcnMuXG4gKi9cbmZ1bmN0aW9uIHNldHVwQWJvcnRTdHJlYW1SZWFkZXIoXG4gIGNvbnRyb2xsZXI6IEFib3J0Q29udHJvbGxlcixcbiAgcnVuSWQ6IHN0cmluZyxcbiAgc3RyZWFtTmFtZTogc3RyaW5nLFxuICBvcHM6IFByb21pc2U8dm9pZD5bXVxuKTogQWJvcnRDb250cm9sbGVyIHtcbiAgY29uc3QgcmVhZGVyQ2FuY2VsID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuXG4gIG9wcy5wdXNoKFxuICAgIChhc3luYyAoKSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZWFkYWJsZSA9IG5ldyBXb3JrZmxvd1NlcnZlclJlYWRhYmxlU3RyZWFtKHJ1bklkLCBzdHJlYW1OYW1lKTtcbiAgICAgICAgY29uc3QgcmVhZGVyID0gcmVhZGFibGUuZ2V0UmVhZGVyKCk7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IFByb21pc2UucmFjZShbXG4gICAgICAgICAgcmVhZGVyLnJlYWQoKSxcbiAgICAgICAgICBuZXcgUHJvbWlzZTx7IHZhbHVlOiB1bmRlZmluZWQ7IGRvbmU6IHRydWUgfT4oKHJlc29sdmUpID0+IHtcbiAgICAgICAgICAgIGlmIChyZWFkZXJDYW5jZWwuc2lnbmFsLmFib3J0ZWQpIHtcbiAgICAgICAgICAgICAgcmVzb2x2ZSh7IHZhbHVlOiB1bmRlZmluZWQsIGRvbmU6IHRydWUgfSk7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlYWRlckNhbmNlbC5zaWduYWwuYWRkRXZlbnRMaXN0ZW5lcihcbiAgICAgICAgICAgICAgJ2Fib3J0JyxcbiAgICAgICAgICAgICAgKCkgPT4gcmVzb2x2ZSh7IHZhbHVlOiB1bmRlZmluZWQsIGRvbmU6IHRydWUgfSksXG4gICAgICAgICAgICAgIHsgb25jZTogdHJ1ZSB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0pLFxuICAgICAgICBdKTtcbiAgICAgICAgcmVhZGVyLnJlbGVhc2VMb2NrKCk7XG4gICAgICAgIGlmIChyZXN1bHQudmFsdWUgJiYgIXJlc3VsdC5kb25lKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIEh5ZHJhdGUgdmlhIHRoZSBzYW1lIG1hY2hpbmVyeSB0aGUgd3JpdGVyIHVzZWQgc28gdGhlIHJlYXNvblxuICAgICAgICAgICAgLy8gcm91bmQtdHJpcHMgd2l0aCBmdWxsIHR5cGUgZmlkZWxpdHkuIEVuY3J5cHRpb24ga2V5IChpZiBhbnkpXG4gICAgICAgICAgICAvLyBjb21lcyBmcm9tIHRoZSBzdGVwIGNvbnRleHQg4oCUIHNldCB1cCBieSB0aGUgc3RlcCBoYW5kbGVyIGJlZm9yZVxuICAgICAgICAgICAgLy8gdGhpcyByZWFkZXIgcnVucy4gRmFsbGJhY2sgdG8gdW5kZWZpbmVkIGZvciBleHRlcm5hbC1jb250ZXh0XG4gICAgICAgICAgICAvLyByZXZpdmVzICh0aGUgaHlkcmF0ZSBwYXRoIGlzIGVuY3J5cHRpb24ta2V5LXRvbGVyYW50KS5cbiAgICAgICAgICAgIGNvbnN0IGN0eEZvcktleSA9IGNvbnRleHRTdG9yYWdlLmdldFN0b3JlKCk7XG4gICAgICAgICAgICBjb25zdCBkYXRhID0gKGF3YWl0IGh5ZHJhdGVTdGVwQXJndW1lbnRzKFxuICAgICAgICAgICAgICByZXN1bHQudmFsdWUsXG4gICAgICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgICAgICBjdHhGb3JLZXk/LmVuY3J5cHRpb25LZXlcbiAgICAgICAgICAgICkpIGFzIHsgcmVhc29uPzogdW5rbm93biB9IHwgdW5kZWZpbmVkO1xuICAgICAgICAgICAgY29udHJvbGxlci5hYm9ydChkYXRhPy5yZWFzb24pO1xuICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgY29udHJvbGxlci5hYm9ydCgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIFN0cmVhbSByZWFkIGZhaWxlZCDigJQgc2lnbmFsIHdvbid0IHByb3BhZ2F0ZSBpbiByZWFsLXRpbWUsXG4gICAgICAgIC8vIGJ1dCBob29rLWJhc2VkIHByb3BhZ2F0aW9uIG9uIG5leHQgcmVwbGF5IHByb3ZpZGVzIGZhbGxiYWNrXG4gICAgICB9XG4gICAgfSkoKVxuICApO1xuXG4gIHJldHVybiByZWFkZXJDYW5jZWw7XG59XG5cbi8qKlxuICogU3RvcmVzIGFib3J0IHNlcmlhbGl6YXRpb24gc3ltYm9scyBhbmQgdGhlIHJlYWRlckNhbmNlbCBjb250cm9sbGVyXG4gKiBvbiBib3RoIHRoZSBjb250cm9sbGVyIGFuZCBpdHMgc2lnbmFsLlxuICovXG5mdW5jdGlvbiB0YWdBYm9ydFBhaXIoXG4gIGNvbnRyb2xsZXI6IEFib3J0Q29udHJvbGxlcixcbiAgdmFsdWU6IHsgc3RyZWFtTmFtZTogc3RyaW5nOyBob29rVG9rZW46IHN0cmluZyB9LFxuICByZWFkZXJDYW5jZWw/OiBBYm9ydENvbnRyb2xsZXJcbik6IHZvaWQge1xuICBjb25zdCB0YWdnZWRDb250cm9sbGVyID0gY29udHJvbGxlciBhcyBBYm9ydENvbnRyb2xsZXIgJiBBYm9ydEludGVybmFscztcbiAgY29uc3QgdGFnZ2VkU2lnbmFsID0gY29udHJvbGxlci5zaWduYWwgYXMgQWJvcnRTaWduYWwgJiBBYm9ydEludGVybmFscztcbiAgdGFnZ2VkQ29udHJvbGxlcltBQk9SVF9TVFJFQU1fTkFNRV0gPSB2YWx1ZS5zdHJlYW1OYW1lO1xuICB0YWdnZWRDb250cm9sbGVyW0FCT1JUX0hPT0tfVE9LRU5dID0gdmFsdWUuaG9va1Rva2VuO1xuICB0YWdnZWRTaWduYWxbQUJPUlRfU1RSRUFNX05BTUVdID0gdmFsdWUuc3RyZWFtTmFtZTtcbiAgdGFnZ2VkU2lnbmFsW0FCT1JUX0hPT0tfVE9LRU5dID0gdmFsdWUuaG9va1Rva2VuO1xuICBpZiAocmVhZGVyQ2FuY2VsKSB7XG4gICAgdGFnZ2VkQ29udHJvbGxlcltBQk9SVF9SRUFERVJfQ0FOQ0VMXSA9IHJlYWRlckNhbmNlbDtcbiAgICB0YWdnZWRTaWduYWxbQUJPUlRfUkVBREVSX0NBTkNFTF0gPSByZWFkZXJDYW5jZWw7XG4gIH1cbn1cblxuLyoqXG4gKiBQcm9wYWdhdGUgYWJvcnQtaW50ZXJuYWwgc3ltYm9scyBmcm9tIG9uZSBzaWduYWwgdG8gYW5vdGhlci4gVXNlZCBieSB0aGVcbiAqIFJlcXVlc3QgcmV2aXZlciBiZWNhdXNlIGBuZXcgUmVxdWVzdCh1cmwsIHsgc2lnbmFsIH0pYCBjb3BpZXMgdGhlIHNpZ25hbFxuICogaW50ZXJuYWxseSDigJQgdGhlIGNvbnN0cnVjdGVkIGByZXF1ZXN0LnNpZ25hbGAgaXMgYSBmcmVzaCBBYm9ydFNpZ25hbCB0aGF0XG4gKiBkb2Vzbid0IGNhcnJ5IHN5bWJvbHMgZnJvbSB0aGUgc291cmNlLlxuICovXG5mdW5jdGlvbiBjb3B5QWJvcnRJbnRlcm5hbHMoc3JjOiBBYm9ydFNpZ25hbCwgZGVzdDogQWJvcnRTaWduYWwpOiB2b2lkIHtcbiAgY29uc3QgcyA9IHNyYyBhcyBBYm9ydFNpZ25hbCAmIEFib3J0SW50ZXJuYWxzO1xuICBjb25zdCBkID0gZGVzdCBhcyBBYm9ydFNpZ25hbCAmIEFib3J0SW50ZXJuYWxzO1xuICBpZiAoc1tBQk9SVF9TVFJFQU1fTkFNRV0gIT09IHVuZGVmaW5lZCkge1xuICAgIGRbQUJPUlRfU1RSRUFNX05BTUVdID0gc1tBQk9SVF9TVFJFQU1fTkFNRV07XG4gIH1cbiAgaWYgKHNbQUJPUlRfSE9PS19UT0tFTl0gIT09IHVuZGVmaW5lZCkge1xuICAgIGRbQUJPUlRfSE9PS19UT0tFTl0gPSBzW0FCT1JUX0hPT0tfVE9LRU5dO1xuICB9XG4gIGlmIChzW0FCT1JUX1JFQURFUl9DQU5DRUxdICE9PSB1bmRlZmluZWQpIHtcbiAgICBkW0FCT1JUX1JFQURFUl9DQU5DRUxdID0gc1tBQk9SVF9SRUFERVJfQ0FOQ0VMXTtcbiAgfVxufVxuXG4vKipcbiAqIENyZWF0ZXMgYW4gQWJvcnRDb250cm9sbGVyIHdpdGggc3RyZWFtLWJhY2tlZCBhYm9ydCBwcm9wYWdhdGlvbi5cbiAqIFVzZWQgYnkgc3RlcCBhbmQgZXh0ZXJuYWwgcmV2aXZlcnMgd2hlcmUgcmVhbCBhYm9ydCBzaWduYWwgYmVoYXZpb3IgaXMgbmVlZGVkLlxuICpcbiAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBzZXJpYWxpemVkIGFib3J0IGNvbnRyb2xsZXIvc2lnbmFsIGRhdGFcbiAqIEBwYXJhbSBvcHMgLSBUaGUgb3BzIGFycmF5IGZvciB0cmFja2luZyBhc3luYyB3b3JrXG4gKiBAcGFyYW0gcnVuSWQgLSBUaGUgd29ya2Zsb3cgcnVuIElEIChmb3Igc3RyZWFtIHJlYWRzKVxuICogQHJldHVybnMgQSByZWFsIEFib3J0Q29udHJvbGxlciB3aXRoIHBhdGNoZWQgYWJvcnQoKSBtZXRob2RcbiAqL1xuZnVuY3Rpb24gcmV2aXZlQWJvcnRDb250cm9sbGVyKFxuICB2YWx1ZTogU2VyaWFsaXphYmxlU3BlY2lhbFsnQWJvcnRDb250cm9sbGVyJ10sXG4gIG9wczogUHJvbWlzZTx2b2lkPltdLFxuICBydW5JZDogc3RyaW5nXG4pOiBBYm9ydENvbnRyb2xsZXIge1xuICBjb25zdCBjb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuXG4gIGlmICh2YWx1ZS5hYm9ydGVkKSB7XG4gICAgdGFnQWJvcnRQYWlyKGNvbnRyb2xsZXIsIHZhbHVlKTtcbiAgICBjb250cm9sbGVyLmFib3J0KHZhbHVlLnJlYXNvbik7XG4gIH0gZWxzZSBpZiAodmFsdWUuc3RyZWFtTmFtZSkge1xuICAgIGNvbnN0IHJlYWRlckNhbmNlbCA9IHNldHVwQWJvcnRTdHJlYW1SZWFkZXIoXG4gICAgICBjb250cm9sbGVyLFxuICAgICAgcnVuSWQsXG4gICAgICB2YWx1ZS5zdHJlYW1OYW1lLFxuICAgICAgb3BzXG4gICAgKTtcbiAgICB0YWdBYm9ydFBhaXIoY29udHJvbGxlciwgdmFsdWUsIHJlYWRlckNhbmNlbCk7XG4gIH0gZWxzZSB7XG4gICAgdGFnQWJvcnRQYWlyKGNvbnRyb2xsZXIsIHZhbHVlKTtcbiAgfVxuXG4gIC8vIE92ZXJyaWRlIGFib3J0KCkgdG8gYWxzbyB3cml0ZSBzdHJlYW0gKyByZXN1bWUgaG9vayAoZm9yIHN0ZXAtaW5pdGlhdGVkIGFib3J0KVxuICBjb25zdCBvcmlnaW5hbEFib3J0ID0gY29udHJvbGxlci5hYm9ydC5iaW5kKGNvbnRyb2xsZXIpO1xuICBjb250cm9sbGVyLmFib3J0ID0gKHJlYXNvbj86IHVua25vd24pID0+IHtcbiAgICBpZiAoY29udHJvbGxlci5zaWduYWwuYWJvcnRlZCkgcmV0dXJuO1xuICAgIG9yaWdpbmFsQWJvcnQocmVhc29uKTtcblxuICAgIGNvbnN0IGN0eCA9IGNvbnRleHRTdG9yYWdlLmdldFN0b3JlKCk7XG4gICAgaWYgKGN0eCkge1xuICAgICAgY3R4Lm9wcy5wdXNoKFxuICAgICAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBEZWh5ZHJhdGUgdGhlIGFib3J0IHBheWxvYWQgdGhyb3VnaCB0aGUgc2FtZSBtYWNoaW5lcnkgdGhlIGhvb2tcbiAgICAgICAgICAgIC8vIGV2ZW50IHVzZXMgc28gdGhlIGByZWFzb25gIHJvdW5kLXRyaXBzIHdpdGggZnVsbCB0eXBlIGZpZGVsaXR5XG4gICAgICAgICAgICAvLyAoRE9NRXhjZXB0aW9uLCBjdXN0b20gZXJyb3JzLCBldGMuKSBhbmQgcmVzcGVjdHMgdGhlIHJ1bidzXG4gICAgICAgICAgICAvLyBlbmNyeXB0aW9uIGtleSDigJQgc3ltbWV0cmljIHdpdGggd2hhdCB0aGUgc3VzcGVuc2lvbiBoYW5kbGVyXG4gICAgICAgICAgICAvLyB3cml0ZXMgZm9yIHdvcmtmbG93LWluaXRpYXRlZCBhYm9ydHMuXG4gICAgICAgICAgICBjb25zdCBwYXlsb2FkID0gYXdhaXQgZGVoeWRyYXRlU3RlcEFyZ3VtZW50cyhcbiAgICAgICAgICAgICAgeyBhYm9ydGVkOiB0cnVlLCByZWFzb24gfSxcbiAgICAgICAgICAgICAgY3R4LndvcmtmbG93TWV0YWRhdGEud29ya2Zsb3dSdW5JZCxcbiAgICAgICAgICAgICAgY3R4LmVuY3J5cHRpb25LZXlcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjb25zdCB3cml0YWJsZSA9IG5ldyBXb3JrZmxvd1NlcnZlcldyaXRhYmxlU3RyZWFtKFxuICAgICAgICAgICAgICBjdHgud29ya2Zsb3dNZXRhZGF0YS53b3JrZmxvd1J1bklkLFxuICAgICAgICAgICAgICB2YWx1ZS5zdHJlYW1OYW1lXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgY29uc3Qgd3JpdGVyID0gd3JpdGFibGUuZ2V0V3JpdGVyKCk7XG4gICAgICAgICAgICBhd2FpdCB3cml0ZXIud3JpdGUocGF5bG9hZCBhcyBVaW50OEFycmF5KTtcbiAgICAgICAgICAgIGF3YWl0IHdyaXRlci5jbG9zZSgpO1xuICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgLy8gQmVzdC1lZmZvcnQgc3RyZWFtIHdyaXRlXG4gICAgICAgICAgfVxuICAgICAgICB9KSgpXG4gICAgICApO1xuXG4gICAgICBpZiAodmFsdWUuaG9va1Rva2VuKSB7XG4gICAgICAgIC8vIFRoZSBkdXJhYmxlIGhvb2sgcmVzdW1lICh3aGljaCB3cml0ZXMgdGhlIGBob29rX3JlY2VpdmVkYCBldmVudCB0aGF0XG4gICAgICAgIC8vIHJlY29yZHMgdGhpcyBhYm9ydCBpbiB0aGUgd29ya2Zsb3cncyBldmVudCBsb2cpIG11c3QgYmUgY29tbWl0dGVkXG4gICAgICAgIC8vIGJlZm9yZSB0aGUgc3RlcCBjb21wbGV0ZXMuIE90aGVyd2lzZSB0aGUgd29ya2Zsb3cgY29udGludWF0aW9uXG4gICAgICAgIC8vIGVucXVldWVkIGJ5IGBzdGVwX2NvbXBsZXRlZGAgY2FuIGFkdmFuY2UgcGFzdCB0aGUgYWJvcnQg4oCUIGRpc3BhdGNoaW5nXG4gICAgICAgIC8vIGEgbGF0ZXIgc3RlcCB3aXRoIGEgc3RhbGUsIG5vbi1hYm9ydGVkIGBzaWduYWxgIOKAlCBiZWZvcmUgdGhlIGV2ZW50XG4gICAgICAgIC8vIGV4aXN0cy4gUm91dGUgaXQgdG8gYHByZUNvbXBsZXRpb25PcHNgIChhd2FpdGVkIGlubGluZSBiZWZvcmVcbiAgICAgICAgLy8gY29tcGxldGlvbikgcmF0aGVyIHRoYW4gYG9wc2AgKGJlc3QtZWZmb3J0LCBiYWNrZ3JvdW5kKS4gVGhlIHN0cmVhbVxuICAgICAgICAvLyB3cml0ZSBhYm92ZSBzdGF5cyBpbiBgb3BzYDogaXQgbXVzdCBmaXJlIEFTQVAgdG8gcmVhY2ggYW4gaW4tZmxpZ2h0XG4gICAgICAgIC8vIHNpYmxpbmcgc3RlcCBhbmQgaXMgbm90IHRoZSBkdXJhYmxlIHJlY29yZC5cbiAgICAgICAgLy8gU3dhbGxvdyBlcnJvcnMgaGVyZSBzbyB0aGUgcHJvbWlzZSBjYW4gb25seSBldmVyIGVuZm9yY2Ugb3JkZXJpbmdcbiAgICAgICAgLy8gd2hlbiBhd2FpdGVkIChzZWUgdGhlIG5vLXJlamVjdCBjb250cmFjdCBvblxuICAgICAgICAvLyBTdGVwQ29udGV4dC5wcmVDb21wbGV0aW9uT3BzKTsgYSBmYWlsZWQgcmVzdW1lIHJldHJpZXMgb24gbmV4dCByZXBsYXkuXG4gICAgICAgIGNvbnN0IGhvb2tSZXN1bWUgPSAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCB7IHJlc3VtZUhvb2s6IHJlc3VtZUhvb2tGbiB9ID0gYXdhaXQgaW1wb3J0KFxuICAgICAgICAgICAgICAnLi9ydW50aW1lL3Jlc3VtZS1ob29rLmpzJ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGF3YWl0IHJlc3VtZUhvb2tGbih2YWx1ZS5ob29rVG9rZW4sIHtcbiAgICAgICAgICAgICAgYWJvcnRlZDogdHJ1ZSxcbiAgICAgICAgICAgICAgcmVhc29uLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICAvLyBCZXN0LWVmZm9ydCBob29rIHJlc3VtZSDigJQgcmV0cnkgb24gbmV4dCByZXBsYXlcbiAgICAgICAgICB9XG4gICAgICAgIH0pKCk7XG4gICAgICAgIGN0eC5wcmVDb21wbGV0aW9uT3BzLnB1c2goaG9va1Jlc3VtZSk7XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBjb250cm9sbGVyO1xufVxuXG4vKipcbiAqIFJldml2ZXMganVzdCBhbiBBYm9ydFNpZ25hbCB3aXRob3V0IHRoZSBwYXRjaGVkIGFib3J0KCkgb3ZlcmhlYWQuXG4gKiBVc2VkIHdoZW4gb25seSBhIHNpZ25hbCAobm90IGEgY29udHJvbGxlcikgd2FzIHNlcmlhbGl6ZWQuXG4gKi9cbmZ1bmN0aW9uIHJldml2ZUFib3J0U2lnbmFsKFxuICB2YWx1ZTogU2VyaWFsaXphYmxlU3BlY2lhbFsnQWJvcnRTaWduYWwnXSxcbiAgb3BzOiBQcm9taXNlPHZvaWQ+W10sXG4gIHJ1bklkOiBzdHJpbmdcbik6IEFib3J0U2lnbmFsIHtcbiAgY29uc3QgY29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcblxuICBpZiAodmFsdWUuYWJvcnRlZCkge1xuICAgIHRhZ0Fib3J0UGFpcihjb250cm9sbGVyLCB2YWx1ZSk7XG4gICAgY29udHJvbGxlci5hYm9ydCh2YWx1ZS5yZWFzb24pO1xuICB9IGVsc2UgaWYgKHZhbHVlLnN0cmVhbU5hbWUpIHtcbiAgICBjb25zdCByZWFkZXJDYW5jZWwgPSBzZXR1cEFib3J0U3RyZWFtUmVhZGVyKFxuICAgICAgY29udHJvbGxlcixcbiAgICAgIHJ1bklkLFxuICAgICAgdmFsdWUuc3RyZWFtTmFtZSxcbiAgICAgIG9wc1xuICAgICk7XG4gICAgdGFnQWJvcnRQYWlyKGNvbnRyb2xsZXIsIHZhbHVlLCByZWFkZXJDYW5jZWwpO1xuICB9IGVsc2Uge1xuICAgIHRhZ0Fib3J0UGFpcihjb250cm9sbGVyLCB2YWx1ZSk7XG4gIH1cblxuICByZXR1cm4gY29udHJvbGxlci5zaWduYWw7XG59XG5cbi8qKlxuICogQmFzZSByZXZpdmVycyBzaGFyZWQgYWNyb3NzIGFsbCBzZXJpYWxpemF0aW9uIGJvdW5kYXJpZXMuXG4gKiBDb21wb3NlczogY2xhc3MgKyBjb21tb24gcmV2aXZlcnMgZnJvbSB0aGUgbW9kdWxhciBtb2R1bGVzLlxuICpcbiAqIFRoaXMgaXMgZXhwb3J0ZWQgYmVjYXVzZSBzZXJpYWxpemF0aW9uLWZvcm1hdC50cyBhbmQgb3RoZXIgZmlsZXMgcmVmZXJlbmNlIGl0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0Q29tbW9uUmV2aXZlcnMoZ2xvYmFsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0gZ2xvYmFsVGhpcykge1xuICByZXR1cm4ge1xuICAgIC4uLmdldENsYXNzUmV2aXZlcnMoZ2xvYmFsKSxcbiAgICAuLi5nZXRDb21tb25SZXZpdmVyc0Zyb21Nb2R1bGUoZ2xvYmFsKSxcbiAgfSBhcyBjb25zdCBzYXRpc2ZpZXMgUGFydGlhbDxSZXZpdmVycz47XG59XG5cbi8qKlxuICogUmVzb2x2ZSB0aGUgZW5jcnlwdC1vbmx5IGtleSBuZWVkZWQgd2hlbiBhIGNoaWxkIHdyaXRlcyBpbnRvIGFub3RoZXIgcnVuJ3NcbiAqIHN0cmVhbS4gTmV3IGRlc2NyaXB0b3JzIGluY2x1ZGUgdGhlIG93bmVyJ3MgZGVwbG95bWVudCBJRDsgZGVzY3JpcHRvcnNcbiAqIGNyZWF0ZWQgYnkgb2xkZXIgU0RLIHZlcnNpb25zIGZhbGwgYmFjayB0byBsb2FkaW5nIHRoZSBvd25pbmcgcnVuLlxuICovXG5hc3luYyBmdW5jdGlvbiBnZXRGb3J3YXJkZWRXcml0YWJsZUVuY3J5cHRpb25LZXkoXG4gIHJ1bklkOiBzdHJpbmcsXG4gIGRlcGxveW1lbnRJZDogc3RyaW5nIHwgdW5kZWZpbmVkXG4pOiBQcm9taXNlPENyeXB0b0tleSB8IHVuZGVmaW5lZD4ge1xuICBjb25zdCB3b3JsZCA9IGF3YWl0IGdldFdvcmxkTGF6eSgpO1xuICBpZiAoIXdvcmxkLmdldEVuY3J5cHRpb25LZXlGb3JSdW4pIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgY29uc3QgcmF3S2V5ID0gZGVwbG95bWVudElkXG4gICAgPyBhd2FpdCB3b3JsZC5nZXRFbmNyeXB0aW9uS2V5Rm9yUnVuKHJ1bklkLCB7IGRlcGxveW1lbnRJZCB9KVxuICAgIDogYXdhaXQgd29ybGQuZ2V0RW5jcnlwdGlvbktleUZvclJ1bihhd2FpdCB3b3JsZC5ydW5zLmdldChydW5JZCkpO1xuICByZXR1cm4gcmF3S2V5ID8gYXdhaXQgaW1wb3J0S2V5KHJhd0tleSwgWydlbmNyeXB0J10pIDogdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIFJldml2ZXJzIGZvciBkZXNlcmlhbGl6YXRpb24gYm91bmRhcnkgZnJvbSB0aGUgY2xpZW50IHNpZGUsXG4gKiByZWNlaXZpbmcgdGhlIHJldHVybiB2YWx1ZSBmcm9tIHRoZSB3b3JrZmxvdyBoYW5kbGVyLlxuICpcbiAqIEBwYXJhbSBnbG9iYWxcbiAqIEBwYXJhbSBvcHNcbiAqIEBwYXJhbSBydW5JZFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0RXh0ZXJuYWxSZXZpdmVycyhcbiAgZ2xvYmFsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0gZ2xvYmFsVGhpcyxcbiAgb3BzOiBQcm9taXNlPHZvaWQ+W10sXG4gIHJ1bklkOiBzdHJpbmcsXG4gIGNyeXB0b0tleTogRW5jcnlwdGlvbktleVBhcmFtXG4pOiBQYXJ0aWFsPFJldml2ZXJzPiB7XG4gIHJldHVybiB7XG4gICAgLi4uZ2V0Q29tbW9uUmV2aXZlcnMoZ2xvYmFsKSxcblxuICAgIC8vIFN0ZXBGdW5jdGlvbiBzaG91bGQgbm90IGJlIHJldHVybmVkIGZyb20gd29ya2Zsb3dzIHRvIGNsaWVudHNcbiAgICBTdGVwRnVuY3Rpb246ICgpID0+IHtcbiAgICAgIHRocm93IG5ldyBTZXJpYWxpemF0aW9uRXJyb3IoXG4gICAgICAgICdTdGVwIGZ1bmN0aW9ucyBjYW5ub3QgYmUgZGVzZXJpYWxpemVkIGluIGNsaWVudCBjb250ZXh0LiBTdGVwIGZ1bmN0aW9ucyBzaG91bGQgbm90IGJlIHJldHVybmVkIGZyb20gd29ya2Zsb3dzLicsXG4gICAgICAgIHtcbiAgICAgICAgICBoaW50OiAnQSBzdGVwIGZ1bmN0aW9uIHJlZmVyZW5jZSByZWFjaGVkIHRoZSBjbGllbnQuIFJldHVybiBhIHNlcmlhbGl6YWJsZSB2YWx1ZSAoZS5nLiB0aGUgc3RlcCByZXN1bHQpIGluc3RlYWQgb2YgdGhlIHN0ZXAgaXRzZWxmLicsXG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfSxcblxuICAgIFdvcmtmbG93RnVuY3Rpb246ICh2YWx1ZSkgPT5cbiAgICAgIE9iamVjdC5hc3NpZ24oXG4gICAgICAgICgpID0+IHtcbiAgICAgICAgICB0aHJvdyBuZXcgU2VyaWFsaXphdGlvbkVycm9yKFxuICAgICAgICAgICAgJ1dvcmtmbG93IGZ1bmN0aW9ucyBjYW5ub3QgYmUgY2FsbGVkIGRpcmVjdGx5LiBVc2Ugc3RhcnQoKSB0byBpbnZva2UgdGhlbS4nLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBoaW50OiAnV3JhcCB0aGUgd29ya2Zsb3cgd2l0aCBgc3RhcnQod29ya2Zsb3dGbiwgeyAuLi4gfSlgIGZyb20gYHdvcmtmbG93YCB0byBiZWdpbiBhIHJ1biBpbnN0ZWFkIG9mIGludm9raW5nIGl0IGxpa2UgYSBub3JtYWwgZnVuY3Rpb24uJyxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICApO1xuICAgICAgICB9LFxuICAgICAgICB7IHdvcmtmbG93SWQ6IHZhbHVlLndvcmtmbG93SWQgfVxuICAgICAgKSxcblxuICAgIFJlcXVlc3Q6ICh2YWx1ZSkgPT4ge1xuICAgICAgY29uc3QgaW5pdDogUmVxdWVzdEluaXQgJiB7IGR1cGxleD86IHN0cmluZyB9ID0ge1xuICAgICAgICBtZXRob2Q6IHZhbHVlLm1ldGhvZCxcbiAgICAgICAgaGVhZGVyczogbmV3IGdsb2JhbC5IZWFkZXJzKHZhbHVlLmhlYWRlcnMpLFxuICAgICAgICBib2R5OiB2YWx1ZS5ib2R5LFxuICAgICAgICBkdXBsZXg6IHZhbHVlLmR1cGxleCxcbiAgICAgIH07XG4gICAgICBpZiAodmFsdWUuc2lnbmFsKSBpbml0LnNpZ25hbCA9IHZhbHVlLnNpZ25hbDtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSBuZXcgZ2xvYmFsLlJlcXVlc3QodmFsdWUudXJsLCBpbml0KTtcbiAgICAgIC8vIFRoZSBSZXF1ZXN0IGNvbnN0cnVjdG9yIGNyZWF0ZXMgYW4gaW50ZXJuYWwgc2lnbmFsIGNvcHksIHNvIHRoZVxuICAgICAgLy8gYWJvcnQtaW50ZXJuYWwgc3ltYm9scyBzZXQgYnkgcmV2aXZlQWJvcnRTaWduYWwgZG9uJ3QgcHJvcGFnYXRlLlxuICAgICAgLy8gUmUtdGFnIHRoZSByZXF1ZXN0J3Mgb3duIHNpZ25hbCBzbyBjYW5jZWxBYm9ydFJlYWRlcnMgY2FuIGZpbmQgaXQuXG4gICAgICBpZiAodmFsdWUuc2lnbmFsKSBjb3B5QWJvcnRJbnRlcm5hbHModmFsdWUuc2lnbmFsLCByZXF1ZXN0LnNpZ25hbCk7XG4gICAgICByZXR1cm4gcmVxdWVzdDtcbiAgICB9LFxuICAgIFJlc3BvbnNlOiAodmFsdWUpID0+IHtcbiAgICAgIC8vIE5vdGU6IFJlc3BvbnNlIGNvbnN0cnVjdG9yIG9ubHkgYWNjZXB0cyBzdGF0dXMsIHN0YXR1c1RleHQsIGFuZCBoZWFkZXJzXG4gICAgICAvLyBUaGUgdHlwZSwgdXJsLCBhbmQgcmVkaXJlY3RlZCBwcm9wZXJ0aWVzIGFyZSByZWFkLW9ubHkgYW5kIHNldCBieSB0aGUgY29uc3RydWN0b3JcbiAgICAgIHJldHVybiBuZXcgZ2xvYmFsLlJlc3BvbnNlKHZhbHVlLmJvZHksIHtcbiAgICAgICAgc3RhdHVzOiB2YWx1ZS5zdGF0dXMsXG4gICAgICAgIHN0YXR1c1RleHQ6IHZhbHVlLnN0YXR1c1RleHQsXG4gICAgICAgIGhlYWRlcnM6IG5ldyBnbG9iYWwuSGVhZGVycyh2YWx1ZS5oZWFkZXJzKSxcbiAgICAgIH0pO1xuICAgIH0sXG4gICAgUmVhZGFibGVTdHJlYW06ICh2YWx1ZSkgPT4ge1xuICAgICAgLy8gSWYgdGhpcyBoYXMgYm9keUluaXQsIGl0IGNhbWUgZnJvbSBhIFJlc3BvbnNlIGNvbnN0cnVjdG9yXG4gICAgICAvLyBDb252ZXJ0IGl0IHRvIGEgUkVBTCBzdHJlYW0gbm93IHRoYXQgd2UncmUgb3V0c2lkZSB0aGUgd29ya2Zsb3dcbiAgICAgIGlmICgnYm9keUluaXQnIGluIHZhbHVlKSB7XG4gICAgICAgIGNvbnN0IGJvZHlJbml0ID0gdmFsdWUuYm9keUluaXQ7XG4gICAgICAgIC8vIFVzZSB0aGUgbmF0aXZlIFJlc3BvbnNlIGNvbnN0cnVjdG9yIHRvIHByb3Blcmx5IGNvbnZlcnQgQm9keUluaXQgdG8gUmVhZGFibGVTdHJlYW1cbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBuZXcgZ2xvYmFsLlJlc3BvbnNlKGJvZHlJbml0KTtcbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmJvZHk7XG4gICAgICB9XG5cbiAgICAgIGlmICh2YWx1ZS50eXBlID09PSAnYnl0ZXMnKSB7XG4gICAgICAgIC8vIEZvciBieXRlIHN0cmVhbXMsIHVzZSBmbHVzaGFibGUgcGlwZSB3aXRoIGxvY2sgcG9sbGluZy5cbiAgICAgICAgLy8gSWYgdGhlIHByb2R1Y2VyIHdyb3RlIGZyYW1lZCBieXRlcyAoZnJhbWluZyA9PT0gJ2ZyYW1lZC12MScpLFxuICAgICAgICAvLyB1bndyYXAgdGhlIGxlbmd0aC1wcmVmaXggZW52ZWxvcGUgYmVmb3JlIGhhbmRpbmcgY2h1bmtzIHRvXG4gICAgICAgIC8vIHRoZSB1c2VyLiBBYnNlbnQgLyAncmF3JyBmcmFtaW5nIG1lYW5zIGxlZ2FjeSByYXcgYnl0ZXMg4oCUXG4gICAgICAgIC8vIHBpcGUgdGhyb3VnaCB1bmNoYW5nZWQgZm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5LlxuICAgICAgICAvL1xuICAgICAgICAvLyBObyBhdXRvLXJlY29ubmVjdCBoZXJlIHlldDogcmF3IGJ5dGUgc3RyZWFtcyBoYXZlIG5vIHdpcmVcbiAgICAgICAgLy8gZnJhbWluZyB0byBjb3VudCBjb25zdW1lZCBjaHVua3Mgd2l0aC4gRnJhbWVkLXYxIGJ5dGUgc3RyZWFtc1xuICAgICAgICAvLyBtYWtlIGZyYW1lIGNvdW50aW5nIHBvc3NpYmxlLCBzbyBleHRlbmRpbmcgdGhlIHJlY29ubmVjdGluZ1xuICAgICAgICAvLyByZWFkZXIgdG8gdGhlbSBpcyBhIHNlcGFyYXRlIGZvbGxvdy11cC5cbiAgICAgICAgY29uc3QgcmVhZGFibGUgPSBuZXcgV29ya2Zsb3dTZXJ2ZXJSZWFkYWJsZVN0cmVhbShcbiAgICAgICAgICBydW5JZCxcbiAgICAgICAgICB2YWx1ZS5uYW1lLFxuICAgICAgICAgIHZhbHVlLnN0YXJ0SW5kZXhcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3Qgc3RhdGUgPSBjcmVhdGVGbHVzaGFibGVTdGF0ZSgpO1xuICAgICAgICBvcHMucHVzaChzdGF0ZS5wcm9taXNlKTtcblxuICAgICAgICAvLyBDcmVhdGUgYW4gaWRlbnRpdHkgKG9yIHVuZnJhbWluZykgdHJhbnNmb3JtIHRvIGdpdmUgdGhlIHVzZXIgYSByZWFkYWJsZVxuICAgICAgICBjb25zdCB7IHJlYWRhYmxlOiB1c2VyUmVhZGFibGUsIHdyaXRhYmxlIH0gPVxuICAgICAgICAgIHZhbHVlLmZyYW1pbmcgPT09ICdmcmFtZWQtdjEnXG4gICAgICAgICAgICA/IGdldEJ5dGVVbmZyYW1pbmdTdHJlYW0oKVxuICAgICAgICAgICAgOiBuZXcgZ2xvYmFsLlRyYW5zZm9ybVN0cmVhbSgpO1xuXG4gICAgICAgIC8vIFN0YXJ0IHRoZSBmbHVzaGFibGUgcGlwZSBpbiB0aGUgYmFja2dyb3VuZFxuICAgICAgICBmbHVzaGFibGVQaXBlKHJlYWRhYmxlLCB3cml0YWJsZSwgc3RhdGUpLmNhdGNoKCgpID0+IHtcbiAgICAgICAgICAvLyBFcnJvcnMgYXJlIGhhbmRsZWQgdmlhIHN0YXRlLnJlamVjdFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBTdGFydCBwb2xsaW5nIHRvIGRldGVjdCB3aGVuIHVzZXIgcmVsZWFzZXMgbG9ja1xuICAgICAgICBwb2xsUmVhZGFibGVMb2NrKHVzZXJSZWFkYWJsZSwgc3RhdGUpO1xuXG4gICAgICAgIHJldHVybiB1c2VyUmVhZGFibGU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBOb24tYnl0ZSBzdHJlYW1zIGNhcnJ5IGxlbmd0aC1wcmVmaXhlZCBmcmFtZXMsIHNvIHdlIGNhbiBjb3VudFxuICAgICAgICAvLyBjb21wbGV0ZWQgZnJhbWVzIGFuZCB0cmFuc3BhcmVudGx5IHJlY29ubmVjdCB3aGVuIHRoZSBzZXJ2ZXJcbiAgICAgICAgLy8gc3RyZWFtIGNvbm5lY3Rpb24gdGltZXMgb3V0IG1pZC1ydW4uXG4gICAgICAgIGNvbnN0IHJlYWRhYmxlID0gY3JlYXRlUmVjb25uZWN0aW5nRnJhbWVkU3RyZWFtKFxuICAgICAgICAgIHJ1bklkLFxuICAgICAgICAgIHZhbHVlLm5hbWUsXG4gICAgICAgICAgdmFsdWUuc3RhcnRJbmRleFxuICAgICAgICApO1xuICAgICAgICBjb25zdCB0cmFuc2Zvcm0gPSBnZXREZXNlcmlhbGl6ZVN0cmVhbShcbiAgICAgICAgICBnZXRFeHRlcm5hbFJldml2ZXJzKGdsb2JhbCwgb3BzLCBydW5JZCwgY3J5cHRvS2V5KSxcbiAgICAgICAgICBjcnlwdG9LZXlcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3Qgc3RhdGUgPSBjcmVhdGVGbHVzaGFibGVTdGF0ZSgpO1xuICAgICAgICBvcHMucHVzaChzdGF0ZS5wcm9taXNlKTtcblxuICAgICAgICAvLyBTdGFydCB0aGUgZmx1c2hhYmxlIHBpcGUgaW4gdGhlIGJhY2tncm91bmRcbiAgICAgICAgZmx1c2hhYmxlUGlwZShyZWFkYWJsZSwgdHJhbnNmb3JtLndyaXRhYmxlLCBzdGF0ZSkuY2F0Y2goKCkgPT4ge1xuICAgICAgICAgIC8vIEVycm9ycyBhcmUgaGFuZGxlZCB2aWEgc3RhdGUucmVqZWN0XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFN0YXJ0IHBvbGxpbmcgdG8gZGV0ZWN0IHdoZW4gdXNlciByZWxlYXNlcyBsb2NrXG4gICAgICAgIHBvbGxSZWFkYWJsZUxvY2sodHJhbnNmb3JtLnJlYWRhYmxlLCBzdGF0ZSk7XG5cbiAgICAgICAgcmV0dXJuIHRyYW5zZm9ybS5yZWFkYWJsZTtcbiAgICAgIH1cbiAgICB9LFxuICAgIFdyaXRhYmxlU3RyZWFtOiAodmFsdWUpID0+IHtcbiAgICAgIC8vIFNhbWUgaGFuZGxpbmcgYXMgYGdldFN0ZXBSZXZpdmVycy5Xcml0YWJsZVN0cmVhbWAg4oCUIHNlZSBjb21tZW50c1xuICAgICAgLy8gdGhlcmUgZm9yIHRoZSBjcm9zcy1ydW4gY2FzZSAod3JpdGFibGUgY2FycmllcyBgcnVuSWRgIGZyb21cbiAgICAgIC8vIHBhcmVudCDihpIgY2hpbGQgZm9yd2FyZGluZyB2aWEgYHN0YXJ0KClgKS5cbiAgICAgIGNvbnN0IHRhcmdldFJ1bklkID0gdHlwZW9mIHZhbHVlLnJ1bklkID09PSAnc3RyaW5nJyA/IHZhbHVlLnJ1bklkIDogcnVuSWQ7XG4gICAgICBjb25zdCB0YXJnZXRLZXk6IEVuY3J5cHRpb25LZXlQYXJhbSA9XG4gICAgICAgIHRhcmdldFJ1bklkID09PSBydW5JZFxuICAgICAgICAgID8gY3J5cHRvS2V5XG4gICAgICAgICAgOiBnZXRGb3J3YXJkZWRXcml0YWJsZUVuY3J5cHRpb25LZXkodGFyZ2V0UnVuSWQsIHZhbHVlLmRlcGxveW1lbnRJZCk7XG5cbiAgICAgIGNvbnN0IHNlcmlhbGl6ZSA9IGdldFNlcmlhbGl6ZVN0cmVhbShcbiAgICAgICAgZ2V0RXh0ZXJuYWxSZWR1Y2VycyhnbG9iYWwsIG9wcywgdGFyZ2V0UnVuSWQsIHRhcmdldEtleSksXG4gICAgICAgIHRhcmdldEtleVxuICAgICAgKTtcbiAgICAgIGNvbnN0IHNlcnZlcldyaXRhYmxlID0gbmV3IFdvcmtmbG93U2VydmVyV3JpdGFibGVTdHJlYW0oXG4gICAgICAgIHRhcmdldFJ1bklkLFxuICAgICAgICB2YWx1ZS5uYW1lXG4gICAgICApO1xuXG4gICAgICAvLyBDcmVhdGUgZmx1c2hhYmxlIHN0YXRlIGZvciB0aGlzIHN0cmVhbVxuICAgICAgY29uc3Qgc3RhdGUgPSBjcmVhdGVGbHVzaGFibGVTdGF0ZSgpO1xuICAgICAgb3BzLnB1c2goc3RhdGUucHJvbWlzZSk7XG5cbiAgICAgIC8vIFN0YXJ0IHRoZSBmbHVzaGFibGUgcGlwZSBpbiB0aGUgYmFja2dyb3VuZFxuICAgICAgZmx1c2hhYmxlUGlwZShzZXJpYWxpemUucmVhZGFibGUsIHNlcnZlcldyaXRhYmxlLCBzdGF0ZSkuY2F0Y2goKCkgPT4ge1xuICAgICAgICAvLyBFcnJvcnMgYXJlIGhhbmRsZWQgdmlhIHN0YXRlLnJlamVjdFxuICAgICAgfSk7XG5cbiAgICAgIC8vIFN0YXJ0IHBvbGxpbmcgdG8gZGV0ZWN0IHdoZW4gdXNlciByZWxlYXNlcyBsb2NrXG4gICAgICBwb2xsV3JpdGFibGVMb2NrKHNlcmlhbGl6ZS53cml0YWJsZSwgc3RhdGUpO1xuXG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoc2VyaWFsaXplLndyaXRhYmxlLCBTVFJFQU1fTkFNRV9TWU1CT0wsIHtcbiAgICAgICAgdmFsdWU6IHZhbHVlLm5hbWUsXG4gICAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICAgIH0pO1xuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHNlcmlhbGl6ZS53cml0YWJsZSwgU1RSRUFNX1NFUlZFUl9SVU5fSURfU1lNQk9MLCB7XG4gICAgICAgIHZhbHVlOiB0YXJnZXRSdW5JZCxcbiAgICAgICAgd3JpdGFibGU6IGZhbHNlLFxuICAgICAgfSk7XG4gICAgICBpZiAodHlwZW9mIHZhbHVlLmRlcGxveW1lbnRJZCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFxuICAgICAgICAgIHNlcmlhbGl6ZS53cml0YWJsZSxcbiAgICAgICAgICBTVFJFQU1fU0VSVkVSX0RFUExPWU1FTlRfSURfU1lNQk9MLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHZhbHVlOiB2YWx1ZS5kZXBsb3ltZW50SWQsXG4gICAgICAgICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gc2VyaWFsaXplLndyaXRhYmxlO1xuICAgIH0sXG5cbiAgICBBYm9ydENvbnRyb2xsZXI6ICh2YWx1ZSkgPT4gcmV2aXZlQWJvcnRDb250cm9sbGVyKHZhbHVlLCBvcHMsIHJ1bklkKSxcbiAgICBBYm9ydFNpZ25hbDogKHZhbHVlKSA9PiByZXZpdmVBYm9ydFNpZ25hbCh2YWx1ZSwgb3BzLCBydW5JZCksXG4gIH07XG59XG5cbi8qKlxuICogUmV2aXZlcnMgZm9yIGRlc2VyaWFsaXphdGlvbiBib3VuZGFyeSBmcm9tIHdpdGhpbiB0aGUgd29ya2Zsb3cgZXhlY3V0aW9uXG4gKiBlbnZpcm9ubWVudCwgcmVjZWl2aW5nIGFyZ3VtZW50cyBmcm9tIHRoZSBjbGllbnQgc2lkZSwgYW5kIHJldHVybiB2YWx1ZXNcbiAqIGZyb20gdGhlIHN0ZXBzLlxuICpcbiAqIEBwYXJhbSBnbG9iYWxcbiAqIEByZXR1cm5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRXb3JrZmxvd1Jldml2ZXJzKFxuICBnbG9iYWw6IFJlY29yZDxzdHJpbmcsIGFueT4gPSBnbG9iYWxUaGlzXG4pOiBQYXJ0aWFsPFJldml2ZXJzPiB7XG4gIHJldHVybiB7XG4gICAgLi4uZ2V0Q29tbW9uUmV2aXZlcnMoZ2xvYmFsKSxcbiAgICAvLyBTdGVwRnVuY3Rpb24gcmV2aXZlciBmb3Igd29ya2Zsb3cgY29udGV4dCAtIHVzZXMgdGhlIG1vZHVsYXIgcmV2aXZlclxuICAgIC8vIHdoaWNoIGNhbGxzIFdPUktGTE9XX1VTRV9TVEVQIGZyb20gZ2xvYmFsIHRvIHJlY29uc3RydWN0IHN0ZXAgcHJveGllc1xuICAgIC4uLmdldFN0ZXBGdW5jdGlvblJldml2ZXIoZ2xvYmFsKSxcbiAgICBSZXF1ZXN0OiAodmFsdWUpID0+IHtcbiAgICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZih2YWx1ZSwgZ2xvYmFsLlJlcXVlc3QucHJvdG90eXBlKTtcbiAgICAgIGNvbnN0IHJlc3BvbnNlV3JpdGFibGUgPSB2YWx1ZS5yZXNwb25zZVdyaXRhYmxlO1xuICAgICAgaWYgKHJlc3BvbnNlV3JpdGFibGUpIHtcbiAgICAgICAgKHZhbHVlIGFzIGFueSlbV0VCSE9PS19SRVNQT05TRV9XUklUQUJMRV0gPSByZXNwb25zZVdyaXRhYmxlO1xuICAgICAgICBkZWxldGUgdmFsdWUucmVzcG9uc2VXcml0YWJsZTtcbiAgICAgICAgKHZhbHVlIGFzIGFueSkucmVzcG9uZFdpdGggPSAoKSA9PiB7XG4gICAgICAgICAgdGhyb3cgbmV3IFNlcmlhbGl6YXRpb25FcnJvcihcbiAgICAgICAgICAgICdgcmVzcG9uZFdpdGgoKWAgbXVzdCBiZSBjYWxsZWQgZnJvbSB3aXRoaW4gYSBzdGVwIGZ1bmN0aW9uLicsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGhpbnQ6ICdNb3ZlIHRoZSBgcmVzcG9uZFdpdGgoLi4uKWAgY2FsbCBpbnNpZGUgYSBgXCJ1c2Ugc3RlcFwiYCBmdW5jdGlvbiDigJQgaXQgY2Fubm90IGJlIGludm9rZWQgZnJvbSBhIHdvcmtmbG93IGNvbnRleHQuJyxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICApO1xuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH0sXG4gICAgLy8gV29ya2Zsb3cgZnVuY3Rpb24gcmV2aXZlciBmb3Igd29ya2Zsb3cgY29udGV4dCDigJQgcmV0dXJucyBhIGZ1bmN0aW9uLWxpa2VcbiAgICAvLyBvYmplY3Qgd2l0aCAud29ya2Zsb3dJZCB0aGF0IG1pbWljcyB3aGF0IHRoZSBTV0MgY29tcGlsZXIgcHJvZHVjZXMsXG4gICAgV29ya2Zsb3dGdW5jdGlvbjogKHZhbHVlKSA9PlxuICAgICAgT2JqZWN0LmFzc2lnbihcbiAgICAgICAgKCkgPT4ge1xuICAgICAgICAgIHRocm93IG5ldyBTZXJpYWxpemF0aW9uRXJyb3IoXG4gICAgICAgICAgICAnV29ya2Zsb3cgZnVuY3Rpb25zIGNhbm5vdCBiZSBjYWxsZWQgZGlyZWN0bHkuIFVzZSBzdGFydCgpIHRvIGludm9rZSB0aGVtLicsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGhpbnQ6ICdXcmFwIHRoZSB3b3JrZmxvdyB3aXRoIGBzdGFydCh3b3JrZmxvd0ZuLCB7IC4uLiB9KWAgZnJvbSBgd29ya2Zsb3dgIHRvIGJlZ2luIGEgcnVuIGluc3RlYWQgb2YgaW52b2tpbmcgaXQgbGlrZSBhIG5vcm1hbCBmdW5jdGlvbi4nLFxuICAgICAgICAgICAgfVxuICAgICAgICAgICk7XG4gICAgICAgIH0sXG4gICAgICAgIHsgd29ya2Zsb3dJZDogdmFsdWUud29ya2Zsb3dJZCB9XG4gICAgICApLFxuICAgIFJlc3BvbnNlOiAodmFsdWUpID0+IHtcbiAgICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZih2YWx1ZSwgZ2xvYmFsLlJlc3BvbnNlLnByb3RvdHlwZSk7XG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfSxcbiAgICBSZWFkYWJsZVN0cmVhbTogKHZhbHVlKSA9PiB7XG4gICAgICAvLyBDaGVjayBpZiB0aGlzIGlzIGEgQm9keUluaXQgdGhhdCBzaG91bGQgYmUgd3JhcHBlZCBpbiBhIGZha2Ugc3RyZWFtXG4gICAgICBpZiAoJ2JvZHlJbml0JyBpbiB2YWx1ZSkge1xuICAgICAgICAvLyBSZWNyZWF0ZSB0aGUgZmFrZSBzdHJlYW0gd2l0aCB0aGUgQm9keUluaXRcbiAgICAgICAgcmV0dXJuIE9iamVjdC5jcmVhdGUoZ2xvYmFsLlJlYWRhYmxlU3RyZWFtLnByb3RvdHlwZSwge1xuICAgICAgICAgIFtCT0RZX0lOSVRfU1lNQk9MXToge1xuICAgICAgICAgICAgdmFsdWU6IHZhbHVlLmJvZHlJbml0LFxuICAgICAgICAgICAgd3JpdGFibGU6IGZhbHNlLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICAvLyBSZWd1bGFyIHN0cmVhbSBoYW5kbGluZ1xuICAgICAgcmV0dXJuIE9iamVjdC5jcmVhdGUoZ2xvYmFsLlJlYWRhYmxlU3RyZWFtLnByb3RvdHlwZSwge1xuICAgICAgICBbU1RSRUFNX05BTUVfU1lNQk9MXToge1xuICAgICAgICAgIHZhbHVlOiB2YWx1ZS5uYW1lLFxuICAgICAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICAgICAgfSxcbiAgICAgICAgW1NUUkVBTV9UWVBFX1NZTUJPTF06IHtcbiAgICAgICAgICB2YWx1ZTogdmFsdWUudHlwZSxcbiAgICAgICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICAgIH0sXG4gICAgICAgIC8vIENhcnJ5IHRoZSB3aXJlLWZyYW1pbmcgZGVjaXNpb24gdGhyb3VnaCB0aGUgd29ya2Zsb3cgVk0gc29cbiAgICAgICAgLy8gdGhhdCB3aGVuIHRoZSBoYW5kbGUgaXMgbGF0ZXIgcGFzc2VkIHRvIGEgc3RlcCAod2hpY2ggcmVhZHNcbiAgICAgICAgLy8gdGhlIGFjdHVhbCBieXRlcyBmcm9tIHRoZSBzZXJ2ZXIpIHdlIGtub3cgd2hldGhlciB0byB1bmZyYW1lLlxuICAgICAgICAvLyBEZWZhdWx0cyB0byB1bmRlZmluZWQgZm9yIHN0cmVhbXMgd2hvc2Ugc2VyaWFsaXplZCByZWYgZGlkbid0XG4gICAgICAgIC8vIGNhcnJ5IHRoZSBmaWVsZCDigJQgdGhvc2UgYXJlIHRyZWF0ZWQgYXMgbGVnYWN5IHJhdyBieXRlcy5cbiAgICAgICAgW1NUUkVBTV9GUkFNSU5HX1NZTUJPTF06IHtcbiAgICAgICAgICB2YWx1ZTogdmFsdWUuZnJhbWluZyxcbiAgICAgICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9LFxuICAgIFdyaXRhYmxlU3RyZWFtOiAodmFsdWUpID0+IHtcbiAgICAgIGNvbnN0IGRlc2NyaXB0b3I6IFByb3BlcnR5RGVzY3JpcHRvck1hcCA9IHtcbiAgICAgICAgW1NUUkVBTV9OQU1FX1NZTUJPTF06IHtcbiAgICAgICAgICB2YWx1ZTogdmFsdWUubmFtZSxcbiAgICAgICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgICAgLy8gUHJlc2VydmUgdGhlIGZvcmVpZ24gcnVuSWQsIGlmIHByZXNlbnQsIHNvIHRoYXQgd2hlbiB0aGVcbiAgICAgIC8vIGhhbmRsZSBpcyBsYXRlciBwYXNzZWQgdG8gYSBzdGVwIHRoZSB3b3JrZmxvdyByZWR1Y2VyIGNhblxuICAgICAgLy8gZm9yd2FyZCBpdCB0aHJvdWdoIHRvIHRoZSBzdGVwIHJldml2ZXIuXG4gICAgICBpZiAodHlwZW9mIHZhbHVlLnJ1bklkID09PSAnc3RyaW5nJykge1xuICAgICAgICBkZXNjcmlwdG9yW1NUUkVBTV9TRVJWRVJfUlVOX0lEX1NZTUJPTF0gPSB7XG4gICAgICAgICAgdmFsdWU6IHZhbHVlLnJ1bklkLFxuICAgICAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2YgdmFsdWUuZGVwbG95bWVudElkID09PSAnc3RyaW5nJykge1xuICAgICAgICBkZXNjcmlwdG9yW1NUUkVBTV9TRVJWRVJfREVQTE9ZTUVOVF9JRF9TWU1CT0xdID0ge1xuICAgICAgICAgIHZhbHVlOiB2YWx1ZS5kZXBsb3ltZW50SWQsXG4gICAgICAgICAgd3JpdGFibGU6IGZhbHNlLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgcmV0dXJuIE9iamVjdC5jcmVhdGUoZ2xvYmFsLldyaXRhYmxlU3RyZWFtLnByb3RvdHlwZSwgZGVzY3JpcHRvcik7XG4gICAgfSxcblxuICAgIC8vIEFib3J0Q29udHJvbGxlci9BYm9ydFNpZ25hbCByZXZpdmVkIGluc2lkZSB0aGUgd29ya2Zsb3cgVk0uIFVzZSB0aGVcbiAgICAvLyByZWFsIFdvcmtmbG93QWJvcnRTaWduYWwgY2xhc3Mgc28gYWRkRXZlbnRMaXN0ZW5lcignYWJvcnQnLCBmbikgYWN0dWFsbHlcbiAgICAvLyBmaXJlcyB3aGVuIHRoZSBzaWduYWwgYWJvcnRzICh0aGUgcHJldmlvdXMgbm8tb3Agc3R1YiBzaWxlbnRseSBkcm9wcGVkXG4gICAgLy8gbGlzdGVuZXIgcmVnaXN0cmF0aW9ucyDigJQgc2lsZW50IGNvcnJlY3RuZXNzIGJ1ZyBmb3IgbmF0dXJhbCBwYXR0ZXJuc1xuICAgIC8vIGxpa2UgYHNpZ25hbC5hZGRFdmVudExpc3RlbmVyKCdhYm9ydCcsIGZuKWAgYWZ0ZXIgcmVjZWl2aW5nIGEgZGVzZXJpYWxpemVkXG4gICAgLy8gc2lnbmFsKS4gVGhlIHNpZ25hbCBkb2VzIG5vdCBvd24gYSBob29rIHN1YnNjcmlwdGlvbiBoZXJlIOKAlCBhYm9ydCBzdGF0ZVxuICAgIC8vIGlzIGRlbGl2ZXJlZCB2aWEgdGhlIGV4aXN0aW5nIHJlcGxheSBtYWNoaW5lcnkgb24gdGhlIHNvdXJjZSBzaWRlLlxuICAgIEFib3J0Q29udHJvbGxlcjogKHZhbHVlKSA9PiB7XG4gICAgICBjb25zdCBzaWduYWwgPSBuZXcgV29ya2Zsb3dBYm9ydFNpZ25hbCh2YWx1ZS5zdHJlYW1OYW1lLCB2YWx1ZS5ob29rVG9rZW4pO1xuICAgICAgaWYgKHZhbHVlLmFib3J0ZWQpIHNpZ25hbC5fc2V0QWJvcnRlZCh2YWx1ZS5yZWFzb24pO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgW0FCT1JUX1NUUkVBTV9OQU1FXTogdmFsdWUuc3RyZWFtTmFtZSxcbiAgICAgICAgW0FCT1JUX0hPT0tfVE9LRU5dOiB2YWx1ZS5ob29rVG9rZW4sXG4gICAgICAgIHNpZ25hbCxcbiAgICAgICAgYWJvcnQ6ICgpID0+IHt9LFxuICAgICAgfTtcbiAgICB9LFxuICAgIEFib3J0U2lnbmFsOiAodmFsdWUpID0+IHtcbiAgICAgIGNvbnN0IHNpZ25hbCA9IG5ldyBXb3JrZmxvd0Fib3J0U2lnbmFsKHZhbHVlLnN0cmVhbU5hbWUsIHZhbHVlLmhvb2tUb2tlbik7XG4gICAgICBpZiAodmFsdWUuYWJvcnRlZCkgc2lnbmFsLl9zZXRBYm9ydGVkKHZhbHVlLnJlYXNvbik7XG4gICAgICByZXR1cm4gc2lnbmFsO1xuICAgIH0sXG4gIH07XG59XG5cbi8qKlxuICogUmV2aXZlcnMgZm9yIGRlc2VyaWFsaXphdGlvbiBib3VuZGFyeSBmcm9tIHdpdGhpbiB0aGUgc3RlcCBleGVjdXRpb25cbiAqIGVudmlyb25tZW50LCByZWNlaXZpbmcgYXJndW1lbnRzIGZyb20gdGhlIHdvcmtmbG93IGhhbmRsZXIuXG4gKlxuICogQHBhcmFtIGdsb2JhbFxuICogQHBhcmFtIG9wc1xuICogQHBhcmFtIHJ1bklkXG4gKiBAcmV0dXJuc1xuICovXG5mdW5jdGlvbiBnZXRTdGVwUmV2aXZlcnMoXG4gIGdsb2JhbDogUmVjb3JkPHN0cmluZywgYW55PiA9IGdsb2JhbFRoaXMsXG4gIG9wczogUHJvbWlzZTx2b2lkPltdLFxuICBydW5JZDogc3RyaW5nLFxuICBjcnlwdG9LZXk6IEVuY3J5cHRpb25LZXlQYXJhbSxcbiAgZGVwbG95bWVudElkPzogc3RyaW5nXG4pOiBQYXJ0aWFsPFJldml2ZXJzPiB7XG4gIHJldHVybiB7XG4gICAgLi4uZ2V0Q29tbW9uUmV2aXZlcnMoZ2xvYmFsKSxcblxuICAgIC8vIFN0ZXBGdW5jdGlvbiByZXZpdmVyIGZvciBzdGVwIGNvbnRleHQgLSByZXR1cm5zIHJhdyBzdGVwIGZ1bmN0aW9uXG4gICAgLy8gd2l0aCBjbG9zdXJlIHZhcmlhYmxlIHN1cHBvcnQgdmlhIEFzeW5jTG9jYWxTdG9yYWdlLlxuICAgIC8vXG4gICAgLy8gSGFuZGxlcyBmb3VyIGluZGVwZW5kZW50IGZsYWdzIGZyb20gdGhlIHNlcmlhbGl6ZWQgcGF5bG9hZDpcbiAgICAvLyAgIC0gYGNsb3N1cmVWYXJzYDogaW52b2tlIHRoZSBib2R5IGluc2lkZSBhbiBBc3luY0xvY2FsU3RvcmFnZSBmcmFtZVxuICAgIC8vICAgICBzbyB0aGUgU1dDLWVtaXR0ZWQgYFdPUktGTE9XX1NURVBfQ09OVEVYVF9TVE9SQUdFYCBJSUZFIGluIHRoZVxuICAgIC8vICAgICBob2lzdGVkIGJvZHkgY2FuIHB1bGwgdGhlIGNsb3N1cmUgdmFyaWFibGVzIGJhY2sgb3V0LlxuICAgIC8vICAgLSBgYm91bmRUaGlzYDogICBhIGB0aGlzYCB2YWx1ZSBjYXB0dXJlZCBieVxuICAgIC8vICAgICBgdXNlU3RlcCguLi4pLmJpbmQodGhpcylgIGluIHRoZSB3b3JrZmxvdyBidW5kbGUgKGxleGljYWwtYHRoaXNgXG4gICAgLy8gICAgIGFycm93IHN0ZXBzKS4gVGhlIHdyYXBwZXIgaW52b2tlcyB0aGUgYm9keSB2aWFcbiAgICAvLyAgICAgYHN0ZXBGbi5hcHBseShib3VuZFRoaXMsIGFyZ3MpYCBzbyB0aGUgYm9keSBzZWVzIHRoZSBzYW1lXG4gICAgLy8gICAgIGB0aGlzYCBpdCB3b3VsZCBoYXZlIGhhZCBpbiB0aGUgd29ya2Zsb3cgYnVuZGxlLiBQcm9wZXJ0eVxuICAgIC8vICAgICBwcmVzZW5jZSDigJQgbm90IHRydXRoaW5lc3Mg4oCUIGlzIHNpZ25pZmljYW50IGJlY2F1c2VcbiAgICAvLyAgICAgYGJpbmQobnVsbClgIGFuZCBgYmluZCh1bmRlZmluZWQpYCBhcmUgYm90aCBsZWdhbCBhbmQgc2hvdWxkXG4gICAgLy8gICAgIHJvdW5kLXRyaXAgZmFpdGhmdWxseS5cbiAgICAvLyAgIC0gYGJvdW5kQXJnc2A6ICAgcHJlZmlsbGVkIGFyZ3MgZnJvbVxuICAgIC8vICAgICBgdXNlU3RlcCguLi4pLmJpbmQodGhpc0FyZywgeCwgeSlgLiBQcmVwZW5kZWQgdG8gdGhlIGNhbGwgYXJnc1xuICAgIC8vICAgICBzbyBwYXJ0aWFsIGFwcGxpY2F0aW9uIHN1cnZpdmVzIHNlcmlhbGl6YXRpb24uXG4gICAgU3RlcEZ1bmN0aW9uOiAodmFsdWUpID0+IHtcbiAgICAgIGNvbnN0IHN0ZXBJZCA9IHZhbHVlLnN0ZXBJZDtcbiAgICAgIGNvbnN0IGNsb3N1cmVWYXJzID0gdmFsdWUuY2xvc3VyZVZhcnM7XG4gICAgICBjb25zdCBoYXNCb3VuZFRoaXMgPSAnYm91bmRUaGlzJyBpbiB2YWx1ZTtcbiAgICAgIGNvbnN0IGJvdW5kVGhpcyA9IGhhc0JvdW5kVGhpcyA/IHZhbHVlLmJvdW5kVGhpcyA6IHVuZGVmaW5lZDtcbiAgICAgIGNvbnN0IGJvdW5kQXJncyA9IEFycmF5LmlzQXJyYXkodmFsdWUuYm91bmRBcmdzKSA/IHZhbHVlLmJvdW5kQXJncyA6IFtdO1xuXG4gICAgICBjb25zdCBzdGVwRm4gPSBnZXRTdGVwRnVuY3Rpb24oc3RlcElkKTtcbiAgICAgIGlmICghc3RlcEZuKSB7XG4gICAgICAgIHRocm93IG5ldyBTZXJpYWxpemF0aW9uRXJyb3IoXG4gICAgICAgICAgYFN0ZXAgZnVuY3Rpb24gXCIke3N0ZXBJZH1cIiBub3QgZm91bmQuIE1ha2Ugc3VyZSB0aGUgc3RlcCBmdW5jdGlvbiBpcyByZWdpc3RlcmVkLmAsXG4gICAgICAgICAge1xuICAgICAgICAgICAgaGludDogJ01ha2Ugc3VyZSB0aGUgc3RlcCBmaWxlIGlzIGluY2x1ZGVkIGluIHlvdXIgYnVpbGQgKGkuZS4gaXQgaXMgbGlzdGVkIGluIHRoZSB3b3JrZmxvdyBtYW5pZmVzdCksIGFuZCB0aGF0IHRoZSBTV0MgcGx1Z2luIGlzIGNvbmZpZ3VyZWQgZm9yIHRoZSBmaWxlLicsXG4gICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICAvLyBGYXN0IHBhdGg6IG5vdGhpbmcgdG8gd3JhcC5cbiAgICAgIGlmICghY2xvc3VyZVZhcnMgJiYgIWhhc0JvdW5kVGhpcyAmJiBib3VuZEFyZ3MubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiBzdGVwRm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHdyYXBwZWRTdGVwRm4gPSBmdW5jdGlvbiAodGhpczogdW5rbm93biwgLi4uYXJnczogYW55W10pIHtcbiAgICAgICAgY29uc3QgY2FsbFRoaXMgPSBoYXNCb3VuZFRoaXMgPyBib3VuZFRoaXMgOiB0aGlzO1xuICAgICAgICBjb25zdCBjYWxsQXJncyA9IGJvdW5kQXJncy5sZW5ndGggPiAwID8gWy4uLmJvdW5kQXJncywgLi4uYXJnc10gOiBhcmdzO1xuICAgICAgICBpZiAoY2xvc3VyZVZhcnMpIHtcbiAgICAgICAgICBjb25zdCBjdXJyZW50Q29udGV4dCA9IGNvbnRleHRTdG9yYWdlLmdldFN0b3JlKCk7XG4gICAgICAgICAgaWYgKCFjdXJyZW50Q29udGV4dCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFdvcmtmbG93UnVudGltZUVycm9yKFxuICAgICAgICAgICAgICAnQ2Fubm90IGNhbGwgc3RlcCBmdW5jdGlvbiB3aXRoIGNsb3N1cmUgdmFyaWFibGVzIG91dHNpZGUgc3RlcCBjb250ZXh0J1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3QgbmV3Q29udGV4dCA9IHtcbiAgICAgICAgICAgIC4uLmN1cnJlbnRDb250ZXh0LFxuICAgICAgICAgICAgY2xvc3VyZVZhcnMsXG4gICAgICAgICAgfTtcbiAgICAgICAgICByZXR1cm4gY29udGV4dFN0b3JhZ2UucnVuKG5ld0NvbnRleHQsICgpID0+XG4gICAgICAgICAgICBzdGVwRm4uYXBwbHkoY2FsbFRoaXMsIGNhbGxBcmdzKVxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN0ZXBGbi5hcHBseShjYWxsVGhpcywgY2FsbEFyZ3MpO1xuICAgICAgfSBhcyBhbnk7XG5cbiAgICAgIC8vIENvcHkgcHJvcGVydGllcyBmcm9tIG9yaWdpbmFsIHN0ZXAgZnVuY3Rpb25cbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh3cmFwcGVkU3RlcEZuLCAnbmFtZScsIHtcbiAgICAgICAgdmFsdWU6IHN0ZXBGbi5uYW1lLFxuICAgICAgfSk7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkod3JhcHBlZFN0ZXBGbiwgJ3N0ZXBJZCcsIHtcbiAgICAgICAgdmFsdWU6IHN0ZXBJZCxcbiAgICAgICAgd3JpdGFibGU6IGZhbHNlLFxuICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiBmYWxzZSxcbiAgICAgIH0pO1xuICAgICAgaWYgKHN0ZXBGbi5tYXhSZXRyaWVzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgd3JhcHBlZFN0ZXBGbi5tYXhSZXRyaWVzID0gc3RlcEZuLm1heFJldHJpZXM7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB3cmFwcGVkU3RlcEZuO1xuICAgIH0sXG5cbiAgICBXb3JrZmxvd0Z1bmN0aW9uOiAodmFsdWUpID0+XG4gICAgICBPYmplY3QuYXNzaWduKFxuICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgdGhyb3cgbmV3IFNlcmlhbGl6YXRpb25FcnJvcihcbiAgICAgICAgICAgICdXb3JrZmxvdyBmdW5jdGlvbnMgY2Fubm90IGJlIGNhbGxlZCBkaXJlY3RseS4gVXNlIHN0YXJ0KCkgdG8gaW52b2tlIHRoZW0uJyxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgaGludDogJ1dyYXAgdGhlIHdvcmtmbG93IHdpdGggYHN0YXJ0KHdvcmtmbG93Rm4sIHsgLi4uIH0pYCBmcm9tIGB3b3JrZmxvd2AgdG8gYmVnaW4gYSBydW4gaW5zdGVhZCBvZiBpbnZva2luZyBpdCBsaWtlIGEgbm9ybWFsIGZ1bmN0aW9uLicsXG4gICAgICAgICAgICB9XG4gICAgICAgICAgKTtcbiAgICAgICAgfSxcbiAgICAgICAgeyB3b3JrZmxvd0lkOiB2YWx1ZS53b3JrZmxvd0lkIH1cbiAgICAgICksXG5cbiAgICBSZXF1ZXN0OiAodmFsdWUpID0+IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlV3JpdGFibGUgPSB2YWx1ZS5yZXNwb25zZVdyaXRhYmxlO1xuICAgICAgY29uc3QgaW5pdDogUmVxdWVzdEluaXQgJiB7IGR1cGxleD86IHN0cmluZyB9ID0ge1xuICAgICAgICBtZXRob2Q6IHZhbHVlLm1ldGhvZCxcbiAgICAgICAgaGVhZGVyczogbmV3IGdsb2JhbC5IZWFkZXJzKHZhbHVlLmhlYWRlcnMpLFxuICAgICAgICBib2R5OiB2YWx1ZS5ib2R5LFxuICAgICAgICBkdXBsZXg6IHZhbHVlLmR1cGxleCxcbiAgICAgIH07XG4gICAgICBpZiAodmFsdWUuc2lnbmFsKSBpbml0LnNpZ25hbCA9IHZhbHVlLnNpZ25hbDtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSBuZXcgZ2xvYmFsLlJlcXVlc3QodmFsdWUudXJsLCBpbml0KTtcbiAgICAgIC8vIFRoZSBSZXF1ZXN0IGNvbnN0cnVjdG9yIGNyZWF0ZXMgYW4gaW50ZXJuYWwgc2lnbmFsIGNvcHksIHNvIHRoZVxuICAgICAgLy8gYWJvcnQtaW50ZXJuYWwgc3ltYm9scyBzZXQgYnkgcmV2aXZlQWJvcnRTaWduYWwgZG9uJ3QgcHJvcGFnYXRlLlxuICAgICAgLy8gUmUtdGFnIHRoZSByZXF1ZXN0J3Mgb3duIHNpZ25hbCBzbyBjYW5jZWxBYm9ydFJlYWRlcnMgY2FuIGZpbmQgaXQuXG4gICAgICBpZiAodmFsdWUuc2lnbmFsKSBjb3B5QWJvcnRJbnRlcm5hbHModmFsdWUuc2lnbmFsLCByZXF1ZXN0LnNpZ25hbCk7XG4gICAgICBpZiAocmVzcG9uc2VXcml0YWJsZSkge1xuICAgICAgICByZXF1ZXN0LnJlc3BvbmRXaXRoID0gYXN5bmMgKHJlc3BvbnNlOiBSZXNwb25zZSkgPT4ge1xuICAgICAgICAgIGNvbnN0IHdyaXRlciA9IHJlc3BvbnNlV3JpdGFibGUuZ2V0V3JpdGVyKCk7XG4gICAgICAgICAgYXdhaXQgd3JpdGVyLndyaXRlKHJlc3BvbnNlKTtcbiAgICAgICAgICBhd2FpdCB3cml0ZXIuY2xvc2UoKTtcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXF1ZXN0O1xuICAgIH0sXG4gICAgUmVzcG9uc2U6ICh2YWx1ZSkgPT4ge1xuICAgICAgLy8gTm90ZTogUmVzcG9uc2UgY29uc3RydWN0b3Igb25seSBhY2NlcHRzIHN0YXR1cywgc3RhdHVzVGV4dCwgYW5kIGhlYWRlcnNcbiAgICAgIC8vIFRoZSB0eXBlLCB1cmwsIGFuZCByZWRpcmVjdGVkIHByb3BlcnRpZXMgYXJlIHJlYWQtb25seSBhbmQgc2V0IGJ5IHRoZSBjb25zdHJ1Y3RvclxuICAgICAgcmV0dXJuIG5ldyBnbG9iYWwuUmVzcG9uc2UodmFsdWUuYm9keSwge1xuICAgICAgICBzdGF0dXM6IHZhbHVlLnN0YXR1cyxcbiAgICAgICAgc3RhdHVzVGV4dDogdmFsdWUuc3RhdHVzVGV4dCxcbiAgICAgICAgaGVhZGVyczogbmV3IGdsb2JhbC5IZWFkZXJzKHZhbHVlLmhlYWRlcnMpLFxuICAgICAgfSk7XG4gICAgfSxcbiAgICBSZWFkYWJsZVN0cmVhbTogKHZhbHVlKSA9PiB7XG4gICAgICAvLyBJZiB0aGlzIGhhcyBib2R5SW5pdCwgaXQgY2FtZSBmcm9tIGEgUmVzcG9uc2UgY29uc3RydWN0b3JcbiAgICAgIC8vIENvbnZlcnQgaXQgdG8gYSBSRUFMIHN0cmVhbSBub3cgdGhhdCB3ZSdyZSBpbiB0aGUgc3RlcCBlbnZpcm9ubWVudFxuICAgICAgaWYgKCdib2R5SW5pdCcgaW4gdmFsdWUpIHtcbiAgICAgICAgY29uc3QgYm9keUluaXQgPSB2YWx1ZS5ib2R5SW5pdDtcbiAgICAgICAgLy8gVXNlIHRoZSBuYXRpdmUgUmVzcG9uc2UgY29uc3RydWN0b3IgdG8gcHJvcGVybHkgY29udmVydCBCb2R5SW5pdCB0byBSZWFkYWJsZVN0cmVhbVxuICAgICAgICBjb25zdCByZXNwb25zZSA9IG5ldyBnbG9iYWwuUmVzcG9uc2UoYm9keUluaXQpO1xuICAgICAgICByZXR1cm4gcmVzcG9uc2UuYm9keTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVhZGFibGUgPSBuZXcgV29ya2Zsb3dTZXJ2ZXJSZWFkYWJsZVN0cmVhbShydW5JZCwgdmFsdWUubmFtZSk7XG4gICAgICBpZiAodmFsdWUudHlwZSA9PT0gJ2J5dGVzJykge1xuICAgICAgICAvLyBGb3IgYnl0ZSBzdHJlYW1zLCB1c2UgZmx1c2hhYmxlIHBpcGUgd2l0aCBsb2NrIHBvbGxpbmcuXG4gICAgICAgIC8vIElmIHRoZSBwcm9kdWNlciB3cm90ZSBmcmFtZWQgYnl0ZXMgKGZyYW1pbmcgPT09ICdmcmFtZWQtdjEnKSxcbiAgICAgICAgLy8gdW53cmFwIHRoZSBsZW5ndGgtcHJlZml4IGVudmVsb3BlIGJlZm9yZSBoYW5kaW5nIGNodW5rcyB0b1xuICAgICAgICAvLyB0aGUgdXNlciBzdGVwLiBBYnNlbnQgLyAncmF3JyBmcmFtaW5nIG1lYW5zIGxlZ2FjeSByYXcgYnl0ZXMg4oCUXG4gICAgICAgIC8vIHBpcGUgdGhyb3VnaCB1bmNoYW5nZWQgZm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5LlxuICAgICAgICBjb25zdCBzdGF0ZSA9IGNyZWF0ZUZsdXNoYWJsZVN0YXRlKCk7XG4gICAgICAgIG9wcy5wdXNoKHN0YXRlLnByb21pc2UpO1xuXG4gICAgICAgIC8vIENyZWF0ZSBhbiBpZGVudGl0eSAob3IgdW5mcmFtaW5nKSB0cmFuc2Zvcm0gdG8gZ2l2ZSB0aGUgdXNlciBhIHJlYWRhYmxlXG4gICAgICAgIGNvbnN0IHsgcmVhZGFibGU6IHVzZXJSZWFkYWJsZSwgd3JpdGFibGUgfSA9XG4gICAgICAgICAgdmFsdWUuZnJhbWluZyA9PT0gJ2ZyYW1lZC12MSdcbiAgICAgICAgICAgID8gZ2V0Qnl0ZVVuZnJhbWluZ1N0cmVhbSgpXG4gICAgICAgICAgICA6IG5ldyBnbG9iYWwuVHJhbnNmb3JtU3RyZWFtKCk7XG5cbiAgICAgICAgLy8gU3RhcnQgdGhlIGZsdXNoYWJsZSBwaXBlIGluIHRoZSBiYWNrZ3JvdW5kXG4gICAgICAgIGZsdXNoYWJsZVBpcGUocmVhZGFibGUsIHdyaXRhYmxlLCBzdGF0ZSkuY2F0Y2goKCkgPT4ge1xuICAgICAgICAgIC8vIEVycm9ycyBhcmUgaGFuZGxlZCB2aWEgc3RhdGUucmVqZWN0XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFN0YXJ0IHBvbGxpbmcgdG8gZGV0ZWN0IHdoZW4gdXNlciByZWxlYXNlcyBsb2NrXG4gICAgICAgIHBvbGxSZWFkYWJsZUxvY2sodXNlclJlYWRhYmxlLCBzdGF0ZSk7XG5cbiAgICAgICAgcmV0dXJuIHVzZXJSZWFkYWJsZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IHRyYW5zZm9ybSA9IGdldERlc2VyaWFsaXplU3RyZWFtKFxuICAgICAgICAgIGdldFN0ZXBSZXZpdmVycyhnbG9iYWwsIG9wcywgcnVuSWQsIGNyeXB0b0tleSwgZGVwbG95bWVudElkKSxcbiAgICAgICAgICBjcnlwdG9LZXlcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3Qgc3RhdGUgPSBjcmVhdGVGbHVzaGFibGVTdGF0ZSgpO1xuICAgICAgICBvcHMucHVzaChzdGF0ZS5wcm9taXNlKTtcblxuICAgICAgICAvLyBTdGFydCB0aGUgZmx1c2hhYmxlIHBpcGUgaW4gdGhlIGJhY2tncm91bmRcbiAgICAgICAgZmx1c2hhYmxlUGlwZShyZWFkYWJsZSwgdHJhbnNmb3JtLndyaXRhYmxlLCBzdGF0ZSkuY2F0Y2goKCkgPT4ge1xuICAgICAgICAgIC8vIEVycm9ycyBhcmUgaGFuZGxlZCB2aWEgc3RhdGUucmVqZWN0XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFN0YXJ0IHBvbGxpbmcgdG8gZGV0ZWN0IHdoZW4gdXNlciByZWxlYXNlcyBsb2NrXG4gICAgICAgIHBvbGxSZWFkYWJsZUxvY2sodHJhbnNmb3JtLnJlYWRhYmxlLCBzdGF0ZSk7XG5cbiAgICAgICAgcmV0dXJuIHRyYW5zZm9ybS5yZWFkYWJsZTtcbiAgICAgIH1cbiAgICB9LFxuICAgIFdyaXRhYmxlU3RyZWFtOiAodmFsdWUpID0+IHtcbiAgICAgIC8vIFNhbWUtcnVuIGNhc2U6IHRoZSB3cml0YWJsZSBiZWxvbmdzIHRvIHRoZSBjdXJyZW50IHJ1bi4gVXNlIHRoZVxuICAgICAgLy8gbG9jYWwgY3J5cHRvS2V5IGFuZCB3cml0ZSB0byB0aGUgbG9jYWwgcnVuSWQncyBzZXJ2ZXIgc3RyZWFtLlxuICAgICAgLy9cbiAgICAgIC8vIENyb3NzLXJ1biBjYXNlIChwYXJlbnQg4oaSIGNoaWxkIHZpYSBgc3RhcnQoKWApOiB0aGUgZGVzY3JpcHRvclxuICAgICAgLy8gY2FycmllcyB0aGUgb3JpZ2luYWwgYHJ1bklkYCBhbmQgYG5hbWVgLiBPcGVuIGEgc2VydmVyIHdyaXRhYmxlXG4gICAgICAvLyBhZ2FpbnN0IHRoZSBvcmlnaW5hbCBgKHJ1bklkLCBuYW1lKWAgYW5kIHJlc29sdmUgVEhBVCBydW4ncyBrZXlcbiAgICAgIC8vIGZvciBlbmNyeXB0aW9uLiBUaGUgcmVzb2x1dGlvbiBpcyBhc3luYyBidXQgZG9lc24ndCBuZWVkIHRvXG4gICAgICAvLyBibG9jayByZXZpdmVyIHJldHVybiDigJQgYGdldFNlcmlhbGl6ZVN0cmVhbWAgYWNjZXB0cyB0aGVcbiAgICAgIC8vIGBQcm9taXNlPENyeXB0b0tleSB8IHVuZGVmaW5lZD5gIGRpcmVjdGx5IGFuZCBhd2FpdHMgaXQgbGF6aWx5XG4gICAgICAvLyBvbiB0aGUgZmlyc3QgY2h1bmsgd3JpdHRlbi4gVGhlIGtleSBpcyBpbXBvcnRlZCBlbmNyeXB0LW9ubHlcbiAgICAgIC8vIHNvIHRoZSByZWNlaXZpbmcgcnVuIGNhbiBuZXZlciBkZWNyeXB0IGFueXRoaW5nIGVsc2Ugb24gdGhlXG4gICAgICAvLyBvd25pbmcgcnVuJ3Mgc3RyZWFtIOKAlCBpdCBjYW4gb25seSBjb250cmlidXRlIG5ldyB3cml0ZXMuXG4gICAgICBjb25zdCB0YXJnZXRSdW5JZCA9IHR5cGVvZiB2YWx1ZS5ydW5JZCA9PT0gJ3N0cmluZycgPyB2YWx1ZS5ydW5JZCA6IHJ1bklkO1xuICAgICAgY29uc3QgdGFyZ2V0RGVwbG95bWVudElkID1cbiAgICAgICAgdHlwZW9mIHZhbHVlLmRlcGxveW1lbnRJZCA9PT0gJ3N0cmluZydcbiAgICAgICAgICA/IHZhbHVlLmRlcGxveW1lbnRJZFxuICAgICAgICAgIDogdGFyZ2V0UnVuSWQgPT09IHJ1bklkXG4gICAgICAgICAgICA/IGRlcGxveW1lbnRJZFxuICAgICAgICAgICAgOiB1bmRlZmluZWQ7XG4gICAgICBjb25zdCB0YXJnZXRLZXk6IEVuY3J5cHRpb25LZXlQYXJhbSA9XG4gICAgICAgIHRhcmdldFJ1bklkID09PSBydW5JZFxuICAgICAgICAgID8gY3J5cHRvS2V5XG4gICAgICAgICAgOiBnZXRGb3J3YXJkZWRXcml0YWJsZUVuY3J5cHRpb25LZXkodGFyZ2V0UnVuSWQsIHRhcmdldERlcGxveW1lbnRJZCk7XG5cbiAgICAgIGNvbnN0IHNlcmlhbGl6ZSA9IGdldFNlcmlhbGl6ZVN0cmVhbShcbiAgICAgICAgZ2V0U3RlcFJlZHVjZXJzKGdsb2JhbCwgb3BzLCB0YXJnZXRSdW5JZCwgdGFyZ2V0S2V5KSxcbiAgICAgICAgdGFyZ2V0S2V5XG4gICAgICApO1xuICAgICAgY29uc3Qgc2VydmVyV3JpdGFibGUgPSBuZXcgV29ya2Zsb3dTZXJ2ZXJXcml0YWJsZVN0cmVhbShcbiAgICAgICAgdGFyZ2V0UnVuSWQsXG4gICAgICAgIHZhbHVlLm5hbWVcbiAgICAgICk7XG5cbiAgICAgIC8vIENyZWF0ZSBmbHVzaGFibGUgc3RhdGUgZm9yIHRoaXMgc3RyZWFtXG4gICAgICBjb25zdCBzdGF0ZSA9IGNyZWF0ZUZsdXNoYWJsZVN0YXRlKCk7XG4gICAgICBvcHMucHVzaChzdGF0ZS5wcm9taXNlKTtcblxuICAgICAgLy8gU3RhcnQgdGhlIGZsdXNoYWJsZSBwaXBlIGluIHRoZSBiYWNrZ3JvdW5kXG4gICAgICBmbHVzaGFibGVQaXBlKHNlcmlhbGl6ZS5yZWFkYWJsZSwgc2VydmVyV3JpdGFibGUsIHN0YXRlKS5jYXRjaCgoKSA9PiB7XG4gICAgICAgIC8vIEVycm9ycyBhcmUgaGFuZGxlZCB2aWEgc3RhdGUucmVqZWN0XG4gICAgICB9KTtcblxuICAgICAgLy8gU3RhcnQgcG9sbGluZyB0byBkZXRlY3Qgd2hlbiB1c2VyIHJlbGVhc2VzIGxvY2tcbiAgICAgIHBvbGxXcml0YWJsZUxvY2soc2VyaWFsaXplLndyaXRhYmxlLCBzdGF0ZSk7XG5cbiAgICAgIC8vIFJlY29yZCB0aGUgdW5kZXJseWluZyBgKHJ1bklkLCBuYW1lKWAgc28gZG93bnN0cmVhbSByZWR1Y2VycyBjYW5cbiAgICAgIC8vIHJlY29nbml6ZSB0aGF0IHRoaXMgd3JpdGFibGUgaXMgYWxyZWFkeSBiYWNrZWQgYnkgYSB3b3JrZmxvd1xuICAgICAgLy8gc2VydmVyIHN0cmVhbS4gV2hlbiBmb3J3YXJkZWQgYWNyb3NzIGBzdGFydCgpYCBhZ2FpbiDigJQgZS5nLlxuICAgICAgLy8gdGhlIGNoaWxkIHBhc3NlcyB0aGlzIHdyaXRhYmxlIG9uIHRvIGEgZ3JhbmRjaGlsZCDigJQgdGhlXG4gICAgICAvLyBleHRlcm5hbCByZWR1Y2VyIG5lZWRzIGJvdGggdG8gZW1pdCB0aGUgb3JpZ2luYWwgYHJ1bklkYCBpblxuICAgICAgLy8gdGhlIGRlc2NyaXB0b3IuXG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoc2VyaWFsaXplLndyaXRhYmxlLCBTVFJFQU1fTkFNRV9TWU1CT0wsIHtcbiAgICAgICAgdmFsdWU6IHZhbHVlLm5hbWUsXG4gICAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICAgIH0pO1xuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHNlcmlhbGl6ZS53cml0YWJsZSwgU1RSRUFNX1NFUlZFUl9SVU5fSURfU1lNQk9MLCB7XG4gICAgICAgIHZhbHVlOiB0YXJnZXRSdW5JZCxcbiAgICAgICAgd3JpdGFibGU6IGZhbHNlLFxuICAgICAgfSk7XG4gICAgICBpZiAodGFyZ2V0RGVwbG95bWVudElkKSB7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShcbiAgICAgICAgICBzZXJpYWxpemUud3JpdGFibGUsXG4gICAgICAgICAgU1RSRUFNX1NFUlZFUl9ERVBMT1lNRU5UX0lEX1NZTUJPTCxcbiAgICAgICAgICB7XG4gICAgICAgICAgICB2YWx1ZTogdGFyZ2V0RGVwbG95bWVudElkLFxuICAgICAgICAgICAgd3JpdGFibGU6IGZhbHNlLFxuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHNlcmlhbGl6ZS53cml0YWJsZTtcbiAgICB9LFxuXG4gICAgQWJvcnRDb250cm9sbGVyOiAodmFsdWUpID0+IHJldml2ZUFib3J0Q29udHJvbGxlcih2YWx1ZSwgb3BzLCBydW5JZCksXG4gICAgQWJvcnRTaWduYWw6ICh2YWx1ZSkgPT4gcmV2aXZlQWJvcnRTaWduYWwodmFsdWUsIG9wcywgcnVuSWQpLFxuICB9O1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBFbmNyeXB0aW9uIEhlbHBlcnNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFRoZXNlIGRlbGVnYXRlIHRvIHRoZSBtb2R1bGFyIGBlbmNyeXB0YC9gZGVjcnlwdGAgZnJvbSBgLi9zZXJpYWxpemF0aW9uL2VuY3J5cHRpb24uanNgXG4vLyBidXQgYXJlIGtlcHQgYXMgbmFtZWQgZXhwb3J0cyBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkgd2l0aCBleGlzdGluZyBjb25zdW1lcnMuXG5cbi8qKlxuICogRW5jcnlwdCBkYXRhIGlmIHRoZSB3b3JsZCBzdXBwb3J0cyBlbmNyeXB0aW9uLlxuICogUmV0dXJucyBvcmlnaW5hbCBkYXRhIGlmIGVuY3J5cHRpb24gaXMgbm90IGF2YWlsYWJsZS5cbiAqXG4gKiBAZGVwcmVjYXRlZCBVc2UgYGVuY3J5cHRgIGZyb20gYC4vc2VyaWFsaXphdGlvbi9lbmNyeXB0aW9uLmpzYCBpbnN0ZWFkLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbWF5YmVFbmNyeXB0KFxuICBkYXRhOiBVaW50OEFycmF5LFxuICBrZXk6IENyeXB0b0tleSB8IHVuZGVmaW5lZFxuKTogUHJvbWlzZTxVaW50OEFycmF5PiB7XG4gIHJldHVybiAoYXdhaXQgZW5jcnlwdChkYXRhLCBrZXkpKSBhcyBVaW50OEFycmF5O1xufVxuXG4vKipcbiAqIERlY3J5cHQgZGF0YSBpZiBpdCBoYXMgdGhlICdlbmNyJyBwcmVmaXguXG4gKlxuICogQGRlcHJlY2F0ZWQgVXNlIGBkZWNyeXB0YCBmcm9tIGAuL3NlcmlhbGl6YXRpb24vZW5jcnlwdGlvbi5qc2AgaW5zdGVhZC5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG1heWJlRGVjcnlwdChcbiAgZGF0YTogVWludDhBcnJheSB8IHVua25vd24sXG4gIGtleTogQ3J5cHRvS2V5IHwgdW5kZWZpbmVkXG4pOiBQcm9taXNlPFVpbnQ4QXJyYXkgfCB1bmtub3duPiB7XG4gIHJldHVybiBkZWNyeXB0KGRhdGEsIGtleSk7XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIERlaHlkcmF0ZSAvIEh5ZHJhdGUgRnVuY3Rpb25zXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBUaGVzZSBkZWxlZ2F0ZSB0byB0aGUgbW9kdWxhciBtb2RlIG1vZHVsZXMgKHdvcmtmbG93LCBzdGVwLCBjbGllbnQpIHBhc3Npbmdcbi8vIG1vZGUtc3BlY2lmaWMgc3RyZWFtIGFuZCBSZXF1ZXN0L1Jlc3BvbnNlIHJlZHVjZXJzL3Jldml2ZXJzIGFzIGV4dHJhIG9wdGlvbnMuXG4vLyBUaGUgdjFDb21wYXQgcGF0aCBpcyBoYW5kbGVkIGlubGluZSBiZWZvcmUgZGVsZWdhdGluZyB0byB0aGUgbW9kdWxlcy5cblxuLyoqXG4gKiBDYWxsZWQgZnJvbSB0aGUgYHN0YXJ0KClgIGZ1bmN0aW9uIHRvIHNlcmlhbGl6ZSB0aGUgd29ya2Zsb3cgYXJndW1lbnRzXG4gKiBpbnRvIGEgZm9ybWF0IHRoYXQgY2FuIGJlIHNhdmVkIHRvIHRoZSBkYXRhYmFzZSBhbmQgdGhlbiBoeWRyYXRlZCBmcm9tXG4gKiB3aXRoaW4gdGhlIHdvcmtmbG93IGV4ZWN1dGlvbiBlbnZpcm9ubWVudC5cbiAqXG4gKiBAcGFyYW0gdmFsdWUgLSBUaGUgdmFsdWUgdG8gc2VyaWFsaXplXG4gKiBAcGFyYW0gcnVuSWQgLSBUaGUgd29ya2Zsb3cgcnVuIElEIChyZXF1aXJlZCBmb3IgZW5jcnlwdGlvbiBjb250ZXh0KVxuICogQHBhcmFtIGtleSAtIEVuY3J5cHRpb24ga2V5ICh1bmRlZmluZWQgdG8gc2tpcCBlbmNyeXB0aW9uKVxuICogQHBhcmFtIG9wcyAtIFByb21pc2UgYXJyYXkgZm9yIHN0cmVhbSBvcGVyYXRpb25zXG4gKiBAcGFyYW0gZ2xvYmFsIC0gR2xvYmFsIG9iamVjdCBmb3Igc2VyaWFsaXphdGlvbiBjb250ZXh0XG4gKiBAcGFyYW0gdjFDb21wYXQgLSBFbmFibGUgbGVnYWN5IHYxIGNvbXBhdGliaWxpdHkgbW9kZVxuICogQHBhcmFtIGZyYW1lZEJ5dGVTdHJlYW1zIC0gV2hldGhlciB0aGUgdGFyZ2V0IHJ1biBjYW4gZGVjb2RlIHdpcmUtZnJhbWVkXG4gKiAgIGJ5dGUgc3RyZWFtcy4gU2hvdWxkIG1hdGNoIHRoZSB0YXJnZXQgZGVwbG95bWVudCdzIGNhcGFiaWxpdHkg4oCUIHNlZVxuICogICBgZ2V0UnVuQ2FwYWJpbGl0aWVzYCBpbiBgY2FwYWJpbGl0aWVzLnRzYC4gRGVmYXVsdHMgdG8gYGZhbHNlYCBmb3JcbiAqICAgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkgd2l0aCBvbGRlciBydW5zLlxuICogQHJldHVybnMgVGhlIGRlaHlkcmF0ZWQgdmFsdWUgYXMgYmluYXJ5IGRhdGEgKFVpbnQ4QXJyYXkpIHdpdGggZm9ybWF0IHByZWZpeFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZGVoeWRyYXRlV29ya2Zsb3dBcmd1bWVudHMoXG4gIHZhbHVlOiB1bmtub3duLFxuICBydW5JZDogc3RyaW5nLFxuICBrZXk6IENyeXB0b0tleSB8IHVuZGVmaW5lZCxcbiAgb3BzOiBQcm9taXNlPHZvaWQ+W10gPSBbXSxcbiAgZ2xvYmFsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0gZ2xvYmFsVGhpcyxcbiAgdjFDb21wYXQgPSBmYWxzZSxcbiAgZnJhbWVkQnl0ZVN0cmVhbXMgPSBmYWxzZSxcbiAgY29tcHJlc3Npb24gPSBmYWxzZVxuKTogUHJvbWlzZTxVaW50OEFycmF5IHwgdW5rbm93bj4ge1xuICBpZiAodjFDb21wYXQpIHtcbiAgICBjb25zdCBzdHIgPSBzdHJpbmdpZnkoXG4gICAgICB2YWx1ZSxcbiAgICAgIGdldEV4dGVybmFsUmVkdWNlcnMoZ2xvYmFsLCBvcHMsIHJ1bklkLCBrZXksIGZyYW1lZEJ5dGVTdHJlYW1zKVxuICAgICk7XG4gICAgcmV0dXJuIHJldml2ZShzdHIpO1xuICB9XG4gIHRyeSB7XG4gICAgY29uc3QgY29tcHJlc3Npb25TdGF0czogQ29tcHJlc3Npb25TdGF0cyA9IHt9O1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNsaWVudE1vZHVsZS5zZXJpYWxpemUodmFsdWUsIGtleSwge1xuICAgICAgZ2xvYmFsLFxuICAgICAgZXh0cmFSZWR1Y2VyczogZ2V0U3RyZWFtQW5kUmVxdWVzdFJlZHVjZXJzKFxuICAgICAgICBnZXRFeHRlcm5hbFJlZHVjZXJzKGdsb2JhbCwgb3BzLCBydW5JZCwga2V5LCBmcmFtZWRCeXRlU3RyZWFtcylcbiAgICAgICksXG4gICAgICBjb21wcmVzc2lvbixcbiAgICAgIGNvbXByZXNzaW9uU3RhdHMsXG4gICAgfSk7XG4gICAgYXdhaXQgcmVjb3JkQ29tcHJlc3Npb24oY29tcHJlc3Npb25TdGF0cywgJ3NlcmlhbGl6ZScpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgY29uc3QgY2F1c2UgPSB1bndyYXBTZXJpYWxpemF0aW9uQ2F1c2UoZXJyb3IpO1xuICAgIGNvbnN0IHsgbWVzc2FnZSwgaGludCB9ID0gZm9ybWF0U2VyaWFsaXphdGlvbkVycm9yKFxuICAgICAgJ3dvcmtmbG93IGFyZ3VtZW50cycsXG4gICAgICBjYXVzZVxuICAgICk7XG4gICAgdGhyb3cgbmV3IFNlcmlhbGl6YXRpb25FcnJvcihtZXNzYWdlLCB7IGhpbnQsIGNhdXNlIH0pO1xuICB9XG59XG5cbi8qKlxuICogQ2FsbGVkIGZyb20gd29ya2Zsb3cgZXhlY3V0aW9uIGVudmlyb25tZW50IHRvIGh5ZHJhdGUgdGhlIHdvcmtmbG93XG4gKiBhcmd1bWVudHMgZnJvbSB0aGUgZGF0YWJhc2UgYXQgdGhlIHN0YXJ0IG9mIHdvcmtmbG93IGV4ZWN1dGlvbi5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGh5ZHJhdGVXb3JrZmxvd0FyZ3VtZW50cyhcbiAgdmFsdWU6IFVpbnQ4QXJyYXkgfCB1bmtub3duLFxuICBfcnVuSWQ6IHN0cmluZyxcbiAga2V5OiBDcnlwdG9LZXkgfCB1bmRlZmluZWQsXG4gIGdsb2JhbDogUmVjb3JkPHN0cmluZywgYW55PiA9IGdsb2JhbFRoaXMsXG4gIGV4dHJhUmV2aXZlcnM6IFJlY29yZDxzdHJpbmcsICh2YWx1ZTogYW55KSA9PiBhbnk+ID0ge31cbik6IFByb21pc2U8YW55PiB7XG4gIGNvbnN0IGNvbXByZXNzaW9uU3RhdHM6IENvbXByZXNzaW9uU3RhdHMgPSB7fTtcbiAgY29uc3QgaW5mbGF0ZWQgPSBhd2FpdCBkZWNvbXByZXNzKFxuICAgIGF3YWl0IG1heWJlRGVjcnlwdCh2YWx1ZSwga2V5KSxcbiAgICBjb21wcmVzc2lvblN0YXRzXG4gICk7XG4gIGF3YWl0IHJlY29yZENvbXByZXNzaW9uKGNvbXByZXNzaW9uU3RhdHMsICdkZXNlcmlhbGl6ZScpO1xuICByZXR1cm4gd29ya2Zsb3dNb2R1bGUuZGVzZXJpYWxpemUoaW5mbGF0ZWQsIHtcbiAgICBnbG9iYWwsXG4gICAgZXh0cmFSZXZpdmVyczoge1xuICAgICAgLi4uZ2V0U3RyZWFtQW5kUmVxdWVzdFJldml2ZXJzKGdldFdvcmtmbG93UmV2aXZlcnMoZ2xvYmFsKSksXG4gICAgICAuLi5leHRyYVJldml2ZXJzLFxuICAgIH0sXG4gIH0pO1xufVxuXG4vKipcbiAqIERlaHlkcmF0ZSB3b3JrZmxvdyByZXR1cm4gdmFsdWUgZm9yIHN0b3JhZ2UuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkZWh5ZHJhdGVXb3JrZmxvd1JldHVyblZhbHVlKFxuICB2YWx1ZTogdW5rbm93bixcbiAgX3J1bklkOiBzdHJpbmcsXG4gIGtleTogQ3J5cHRvS2V5IHwgdW5kZWZpbmVkLFxuICBnbG9iYWw6IFJlY29yZDxzdHJpbmcsIGFueT4gPSBnbG9iYWxUaGlzLFxuICB2MUNvbXBhdCA9IGZhbHNlLFxuICBjb21wcmVzc2lvbiA9IGZhbHNlXG4pOiBQcm9taXNlPFVpbnQ4QXJyYXkgfCB1bmtub3duPiB7XG4gIGlmICh2MUNvbXBhdCkge1xuICAgIGNvbnN0IHN0ciA9IHN0cmluZ2lmeSh2YWx1ZSwgZ2V0V29ya2Zsb3dSZWR1Y2VycyhnbG9iYWwpKTtcbiAgICByZXR1cm4gcmV2aXZlKHN0cik7XG4gIH1cbiAgdHJ5IHtcbiAgICBjb25zdCBjb21wcmVzc2lvblN0YXRzOiBDb21wcmVzc2lvblN0YXRzID0ge307XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3RlcE1vZHVsZS5zZXJpYWxpemUodmFsdWUsIGtleSwge1xuICAgICAgZ2xvYmFsLFxuICAgICAgZXh0cmFSZWR1Y2VyczogZ2V0U3RyZWFtQW5kUmVxdWVzdFJlZHVjZXJzKGdldFdvcmtmbG93UmVkdWNlcnMoZ2xvYmFsKSksXG4gICAgICBjb21wcmVzc2lvbixcbiAgICAgIGNvbXByZXNzaW9uU3RhdHMsXG4gICAgfSk7XG4gICAgYXdhaXQgcmVjb3JkQ29tcHJlc3Npb24oY29tcHJlc3Npb25TdGF0cywgJ3NlcmlhbGl6ZScpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgY29uc3QgY2F1c2UgPSB1bndyYXBTZXJpYWxpemF0aW9uQ2F1c2UoZXJyb3IpO1xuICAgIGNvbnN0IHsgbWVzc2FnZSwgaGludCB9ID0gZm9ybWF0U2VyaWFsaXphdGlvbkVycm9yKFxuICAgICAgJ3dvcmtmbG93IHJldHVybiB2YWx1ZScsXG4gICAgICBjYXVzZVxuICAgICk7XG4gICAgdGhyb3cgbmV3IFNlcmlhbGl6YXRpb25FcnJvcihtZXNzYWdlLCB7IGhpbnQsIGNhdXNlIH0pO1xuICB9XG59XG5cbi8qKlxuICogQ2FsbGVkIGZyb20gdGhlIGNsaWVudCBzaWRlIHRvIGh5ZHJhdGUgdGhlIHdvcmtmbG93IHJldHVybiB2YWx1ZVxuICogb2YgYSBjb21wbGV0ZWQgd29ya2Zsb3cgcnVuLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaHlkcmF0ZVdvcmtmbG93UmV0dXJuVmFsdWUoXG4gIHZhbHVlOiBVaW50OEFycmF5IHwgdW5rbm93bixcbiAgcnVuSWQ6IHN0cmluZyxcbiAga2V5OiBDcnlwdG9LZXkgfCB1bmRlZmluZWQsXG4gIG9wczogUHJvbWlzZTx2b2lkPltdID0gW10sXG4gIGdsb2JhbDogUmVjb3JkPHN0cmluZywgYW55PiA9IGdsb2JhbFRoaXMsXG4gIGV4dHJhUmV2aXZlcnM6IFJlY29yZDxzdHJpbmcsICh2YWx1ZTogYW55KSA9PiBhbnk+ID0ge31cbik6IFByb21pc2U8YW55PiB7XG4gIGNvbnN0IGNvbXByZXNzaW9uU3RhdHM6IENvbXByZXNzaW9uU3RhdHMgPSB7fTtcbiAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY2xpZW50TW9kdWxlLmRlc2VyaWFsaXplKHZhbHVlLCBrZXksIHtcbiAgICBnbG9iYWwsXG4gICAgZXh0cmFSZXZpdmVyczoge1xuICAgICAgLi4uZ2V0U3RyZWFtQW5kUmVxdWVzdFJldml2ZXJzKFxuICAgICAgICBnZXRFeHRlcm5hbFJldml2ZXJzKGdsb2JhbCwgb3BzLCBydW5JZCwga2V5KVxuICAgICAgKSxcbiAgICAgIC4uLmV4dHJhUmV2aXZlcnMsXG4gICAgfSxcbiAgICBjb21wcmVzc2lvblN0YXRzLFxuICB9KTtcbiAgYXdhaXQgcmVjb3JkQ29tcHJlc3Npb24oY29tcHJlc3Npb25TdGF0cywgJ2Rlc2VyaWFsaXplJyk7XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKlxuICogQ2FsbGVkIGZyb20gdGhlIHdvcmtmbG93IGhhbmRsZXIgd2hlbiBhIHN0ZXAgaXMgYmVpbmcgY3JlYXRlZC5cbiAqIERlaHlkcmF0ZXMgdmFsdWVzIGZyb20gd2l0aGluIHRoZSB3b3JrZmxvdyBleGVjdXRpb24gZW52aXJvbm1lbnQuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkZWh5ZHJhdGVTdGVwQXJndW1lbnRzKFxuICB2YWx1ZTogdW5rbm93bixcbiAgX3J1bklkOiBzdHJpbmcsXG4gIGtleTogQ3J5cHRvS2V5IHwgdW5kZWZpbmVkLFxuICBnbG9iYWw6IFJlY29yZDxzdHJpbmcsIGFueT4gPSBnbG9iYWxUaGlzLFxuICB2MUNvbXBhdCA9IGZhbHNlLFxuICBjb21wcmVzc2lvbiA9IGZhbHNlXG4pOiBQcm9taXNlPFVpbnQ4QXJyYXkgfCB1bmtub3duPiB7XG4gIGlmICh2MUNvbXBhdCkge1xuICAgIGNvbnN0IHN0ciA9IHN0cmluZ2lmeSh2YWx1ZSwgZ2V0V29ya2Zsb3dSZWR1Y2VycyhnbG9iYWwpKTtcbiAgICByZXR1cm4gcmV2aXZlKHN0cik7XG4gIH1cbiAgdHJ5IHtcbiAgICBjb25zdCBjb21wcmVzc2lvblN0YXRzOiBDb21wcmVzc2lvblN0YXRzID0ge307XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3RlcE1vZHVsZS5zZXJpYWxpemUodmFsdWUsIGtleSwge1xuICAgICAgZ2xvYmFsLFxuICAgICAgZXh0cmFSZWR1Y2VyczogZ2V0U3RyZWFtQW5kUmVxdWVzdFJlZHVjZXJzKGdldFdvcmtmbG93UmVkdWNlcnMoZ2xvYmFsKSksXG4gICAgICBjb21wcmVzc2lvbixcbiAgICAgIGNvbXByZXNzaW9uU3RhdHMsXG4gICAgfSk7XG4gICAgYXdhaXQgcmVjb3JkQ29tcHJlc3Npb24oY29tcHJlc3Npb25TdGF0cywgJ3NlcmlhbGl6ZScpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgY29uc3QgY2F1c2UgPSB1bndyYXBTZXJpYWxpemF0aW9uQ2F1c2UoZXJyb3IpO1xuICAgIGNvbnN0IHsgbWVzc2FnZSwgaGludCB9ID0gZm9ybWF0U2VyaWFsaXphdGlvbkVycm9yKCdzdGVwIGFyZ3VtZW50cycsIGNhdXNlKTtcbiAgICB0aHJvdyBuZXcgU2VyaWFsaXphdGlvbkVycm9yKG1lc3NhZ2UsIHsgaGludCwgY2F1c2UgfSk7XG4gIH1cbn1cblxuLyoqXG4gKiBDYWxsZWQgZnJvbSB0aGUgc3RlcCBoYW5kbGVyIHRvIGh5ZHJhdGUgdGhlIGFyZ3VtZW50cyBvZiBhIHN0ZXBcbiAqIGZyb20gdGhlIGRhdGFiYXNlIGF0IHRoZSBzdGFydCBvZiB0aGUgc3RlcCBleGVjdXRpb24uXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoeWRyYXRlU3RlcEFyZ3VtZW50cyhcbiAgdmFsdWU6IFVpbnQ4QXJyYXkgfCB1bmtub3duLFxuICBydW5JZDogc3RyaW5nLFxuICBrZXk6IENyeXB0b0tleSB8IHVuZGVmaW5lZCxcbiAgb3BzOiBQcm9taXNlPGFueT5bXSA9IFtdLFxuICBnbG9iYWw6IFJlY29yZDxzdHJpbmcsIGFueT4gPSBnbG9iYWxUaGlzLFxuICBleHRyYVJldml2ZXJzOiBSZWNvcmQ8c3RyaW5nLCAodmFsdWU6IGFueSkgPT4gYW55PiA9IHt9LFxuICBkZXBsb3ltZW50SWQ/OiBzdHJpbmdcbik6IFByb21pc2U8YW55PiB7XG4gIGNvbnN0IGNvbXByZXNzaW9uU3RhdHM6IENvbXByZXNzaW9uU3RhdHMgPSB7fTtcbiAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc3RlcE1vZHVsZS5kZXNlcmlhbGl6ZSh2YWx1ZSwga2V5LCB7XG4gICAgZ2xvYmFsLFxuICAgIGV4dHJhUmV2aXZlcnM6IHtcbiAgICAgIC4uLmdldFN0cmVhbUFuZFJlcXVlc3RSZXZpdmVycyhcbiAgICAgICAgZ2V0U3RlcFJldml2ZXJzKGdsb2JhbCwgb3BzLCBydW5JZCwga2V5LCBkZXBsb3ltZW50SWQpXG4gICAgICApLFxuICAgICAgLi4uZXh0cmFSZXZpdmVycyxcbiAgICB9LFxuICAgIGNvbXByZXNzaW9uU3RhdHMsXG4gIH0pO1xuICBhd2FpdCByZWNvcmRDb21wcmVzc2lvbihjb21wcmVzc2lvblN0YXRzLCAnZGVzZXJpYWxpemUnKTtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBDYWxsZWQgZnJvbSB0aGUgc3RlcCBoYW5kbGVyIHdoZW4gYSBzdGVwIGhhcyBjb21wbGV0ZWQuXG4gKiBEZWh5ZHJhdGVzIHZhbHVlcyBmcm9tIHdpdGhpbiB0aGUgc3RlcCBleGVjdXRpb24gZW52aXJvbm1lbnRcbiAqIGludG8gYSBmb3JtYXQgdGhhdCBjYW4gYmUgc2F2ZWQgdG8gdGhlIGRhdGFiYXNlLlxuICpcbiAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSB0byBzZXJpYWxpemVcbiAqIEBwYXJhbSBydW5JZCAtIFJ1biBJRCBmb3IgZW5jcnlwdGlvbiBjb250ZXh0XG4gKiBAcGFyYW0ga2V5IC0gRW5jcnlwdGlvbiBrZXkgKHVuZGVmaW5lZCB0byBza2lwIGVuY3J5cHRpb24pXG4gKiBAcGFyYW0gb3BzIC0gUHJvbWlzZSBhcnJheSBmb3Igc3RyZWFtIG9wZXJhdGlvbnNcbiAqIEBwYXJhbSBnbG9iYWwgLSBHbG9iYWwgb2JqZWN0IGZvciBzZXJpYWxpemF0aW9uIGNvbnRleHRcbiAqIEBwYXJhbSB2MUNvbXBhdCAtIEVuYWJsZSBsZWdhY3kgdjEgY29tcGF0aWJpbGl0eSBtb2RlXG4gKiBAcGFyYW0gZnJhbWVkQnl0ZVN0cmVhbXMgLSBXaGV0aGVyIHRoZSB0YXJnZXQgcnVuIGNhbiBkZWNvZGUgd2lyZS1mcmFtZWRcbiAqICAgYnl0ZSBzdHJlYW1zLiBTaG91bGQgbWF0Y2ggdGhlIHRhcmdldCBkZXBsb3ltZW50J3MgY2FwYWJpbGl0eSDigJQgc2VlXG4gKiAgIGBnZXRSdW5DYXBhYmlsaXRpZXNgIGluIGBjYXBhYmlsaXRpZXMudHNgLiBEZWZhdWx0cyB0byBgZmFsc2VgIGZvclxuICogICBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eSB3aXRoIG9sZGVyIHJ1bnMuXG4gKiBAcmV0dXJucyBUaGUgZGVoeWRyYXRlZCB2YWx1ZSBhcyBiaW5hcnkgZGF0YSAoVWludDhBcnJheSkgd2l0aCBmb3JtYXQgcHJlZml4XG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkZWh5ZHJhdGVTdGVwUmV0dXJuVmFsdWUoXG4gIHZhbHVlOiB1bmtub3duLFxuICBydW5JZDogc3RyaW5nLFxuICBrZXk6IENyeXB0b0tleSB8IHVuZGVmaW5lZCxcbiAgb3BzOiBQcm9taXNlPGFueT5bXSA9IFtdLFxuICBnbG9iYWw6IFJlY29yZDxzdHJpbmcsIGFueT4gPSBnbG9iYWxUaGlzLFxuICB2MUNvbXBhdCA9IGZhbHNlLFxuICBmcmFtZWRCeXRlU3RyZWFtcyA9IGZhbHNlLFxuICBjb21wcmVzc2lvbiA9IGZhbHNlXG4pOiBQcm9taXNlPFVpbnQ4QXJyYXkgfCB1bmtub3duPiB7XG4gIGlmICh2MUNvbXBhdCkge1xuICAgIGNvbnN0IHN0ciA9IHN0cmluZ2lmeShcbiAgICAgIHZhbHVlLFxuICAgICAgZ2V0U3RlcFJlZHVjZXJzKGdsb2JhbCwgb3BzLCBydW5JZCwga2V5LCBmcmFtZWRCeXRlU3RyZWFtcylcbiAgICApO1xuICAgIHJldHVybiByZXZpdmUoc3RyKTtcbiAgfVxuICB0cnkge1xuICAgIGNvbnN0IGNvbXByZXNzaW9uU3RhdHM6IENvbXByZXNzaW9uU3RhdHMgPSB7fTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzdGVwTW9kdWxlLnNlcmlhbGl6ZSh2YWx1ZSwga2V5LCB7XG4gICAgICBnbG9iYWwsXG4gICAgICBleHRyYVJlZHVjZXJzOiBnZXRTdHJlYW1BbmRSZXF1ZXN0UmVkdWNlcnMoXG4gICAgICAgIGdldFN0ZXBSZWR1Y2VycyhnbG9iYWwsIG9wcywgcnVuSWQsIGtleSwgZnJhbWVkQnl0ZVN0cmVhbXMpXG4gICAgICApLFxuICAgICAgY29tcHJlc3Npb24sXG4gICAgICBjb21wcmVzc2lvblN0YXRzLFxuICAgIH0pO1xuICAgIGF3YWl0IHJlY29yZENvbXByZXNzaW9uKGNvbXByZXNzaW9uU3RhdHMsICdzZXJpYWxpemUnKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGNvbnN0IGNhdXNlID0gdW53cmFwU2VyaWFsaXphdGlvbkNhdXNlKGVycm9yKTtcbiAgICBjb25zdCB7IG1lc3NhZ2UsIGhpbnQgfSA9IGZvcm1hdFNlcmlhbGl6YXRpb25FcnJvcihcbiAgICAgICdzdGVwIHJldHVybiB2YWx1ZScsXG4gICAgICBjYXVzZVxuICAgICk7XG4gICAgdGhyb3cgbmV3IFNlcmlhbGl6YXRpb25FcnJvcihtZXNzYWdlLCB7IGhpbnQsIGNhdXNlIH0pO1xuICB9XG59XG5cbi8qKlxuICogQ2FsbGVkIGZyb20gdGhlIHN0ZXAgaGFuZGxlciB3aGVuIGEgc3RlcCB0aHJvd3MuIERlaHlkcmF0ZXMgdGhlIHRocm93blxuICogdmFsdWUgZnJvbSB3aXRoaW4gdGhlIHN0ZXAgZXhlY3V0aW9uIGVudmlyb25tZW50IGludG8gYSBmb3JtYXQgdGhhdCBjYW5cbiAqIGJlIHNhdmVkIHRvIHRoZSBkYXRhYmFzZSBpbiBhIGBzdGVwX2ZhaWxlZGAgb3IgYHN0ZXBfcmV0cnlpbmdgIGV2ZW50LlxuICpcbiAqIEFueSBKYXZhU2NyaXB0IHZhbHVlIGNhbiBiZSB0aHJvd24gKHN0cmluZ3MsIG51bWJlcnMsIG9iamVjdHMsIEVycm9ycyxcbiAqIEVycm9yIHN1YmNsYXNzZXMpLCBzbyB0aGUgc2FtZSBzZXJpYWxpemF0aW9uIHBpcGVsaW5lIHVzZWQgZm9yIHN0ZXBcbiAqIGFyZ3VtZW50cyBhbmQgcmV0dXJuIHZhbHVlcyBpcyBhcHBsaWVkIGhlcmUuXG4gKlxuICogQHBhcmFtIHZhbHVlIC0gVGhlIHRocm93biB2YWx1ZSB0byBzZXJpYWxpemUgKGNhbiBiZSBhbnkgdHlwZSlcbiAqIEBwYXJhbSBydW5JZCAtIFJ1biBJRCBmb3IgZW5jcnlwdGlvbiBjb250ZXh0XG4gKiBAcGFyYW0ga2V5IC0gRW5jcnlwdGlvbiBrZXkgKHVuZGVmaW5lZCB0byBza2lwIGVuY3J5cHRpb24pXG4gKiBAcGFyYW0gb3BzIC0gUHJvbWlzZSBhcnJheSBmb3Igc3RyZWFtIG9wZXJhdGlvbnNcbiAqIEBwYXJhbSBnbG9iYWwgLSBHbG9iYWwgb2JqZWN0IGZvciBzZXJpYWxpemF0aW9uIGNvbnRleHRcbiAqIEByZXR1cm5zIFRoZSBkZWh5ZHJhdGVkIHZhbHVlIGFzIGJpbmFyeSBkYXRhIChVaW50OEFycmF5KSB3aXRoIGZvcm1hdCBwcmVmaXhcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlaHlkcmF0ZVN0ZXBFcnJvcihcbiAgdmFsdWU6IHVua25vd24sXG4gIHJ1bklkOiBzdHJpbmcsXG4gIGtleTogQ3J5cHRvS2V5IHwgdW5kZWZpbmVkLFxuICBvcHM6IFByb21pc2U8YW55PltdID0gW10sXG4gIGdsb2JhbDogUmVjb3JkPHN0cmluZywgYW55PiA9IGdsb2JhbFRoaXMsXG4gIGNvbXByZXNzaW9uID0gZmFsc2Vcbik6IFByb21pc2U8VWludDhBcnJheT4ge1xuICB0cnkge1xuICAgIGNvbnN0IHN0ciA9IHN0cmluZ2lmeSh2YWx1ZSwgZ2V0U3RlcFJlZHVjZXJzKGdsb2JhbCwgb3BzLCBydW5JZCwga2V5KSk7XG4gICAgY29uc3QgcGF5bG9hZCA9IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShzdHIpO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSBlbmNvZGVXaXRoRm9ybWF0UHJlZml4KFxuICAgICAgU2VyaWFsaXphdGlvbkZvcm1hdC5ERVZBTFVFX1YxLFxuICAgICAgcGF5bG9hZFxuICAgICkgYXMgVWludDhBcnJheTtcbiAgICAvLyBDb21wcmVzcyBiZWZvcmUgZW5jcnlwdGluZyDigJQgZW5jcnlwdGVkIGJ5dGVzIGRvbid0IGNvbXByZXNzLlxuICAgIGNvbnN0IGNvbXByZXNzaW9uU3RhdHM6IENvbXByZXNzaW9uU3RhdHMgPSB7fTtcbiAgICBjb25zdCBjb21wcmVzc2VkID0gYXdhaXQgY29tcHJlc3MoXG4gICAgICBzZXJpYWxpemVkLFxuICAgICAgY29tcHJlc3Npb24sXG4gICAgICBjb21wcmVzc2lvblN0YXRzXG4gICAgKTtcbiAgICBjb25zdCBlbmNyeXB0ZWQgPSAoYXdhaXQgbWF5YmVFbmNyeXB0KFxuICAgICAgY29tcHJlc3NlZCBhcyBVaW50OEFycmF5LFxuICAgICAga2V5XG4gICAgKSkgYXMgVWludDhBcnJheTtcbiAgICBhd2FpdCByZWNvcmRDb21wcmVzc2lvbihjb21wcmVzc2lvblN0YXRzLCAnc2VyaWFsaXplJyk7XG4gICAgcmV0dXJuIGVuY3J5cHRlZDtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBjb25zdCBjYXVzZSA9IHVud3JhcFNlcmlhbGl6YXRpb25DYXVzZShlcnJvcik7XG4gICAgY29uc3QgeyBtZXNzYWdlLCBoaW50IH0gPSBmb3JtYXRTZXJpYWxpemF0aW9uRXJyb3IoJ3N0ZXAgZXJyb3InLCBjYXVzZSk7XG4gICAgdGhyb3cgbmV3IFNlcmlhbGl6YXRpb25FcnJvcihtZXNzYWdlLCB7IGhpbnQsIGNhdXNlIH0pO1xuICB9XG59XG5cbi8qKlxuICogQ2FsbGVkIGZyb20gdGhlIHdvcmtmbG93IGhhbmRsZXIgd2hlbiByZXBsYXlpbmcgdGhlIGV2ZW50IGxvZyBvZiBhXG4gKiBgc3RlcF9mYWlsZWRgIG9yIGBzdGVwX3JldHJ5aW5nYCBldmVudC4gSHlkcmF0ZXMgdGhlIHRocm93biB2YWx1ZSBmcm9tXG4gKiB0aGUgZGF0YWJhc2Ugc28gdGhlIHdvcmtmbG93IGNhbiBzZWUgdGhlIG9yaWdpbmFsIHRocm93biB2YWx1ZS5cbiAqXG4gKiBAcGFyYW0gdmFsdWUgLSBCaW5hcnkgc2VyaWFsaXplZCBkYXRhIChVaW50OEFycmF5KSB3aXRoIGZvcm1hdCBwcmVmaXhcbiAqIEBwYXJhbSBydW5JZCAtIFJ1biBJRCBmb3IgZGVjcnlwdGlvbiBjb250ZXh0XG4gKiBAcGFyYW0ga2V5IC0gRW5jcnlwdGlvbiBrZXkgKHVuZGVmaW5lZCB0byBza2lwIGRlY3J5cHRpb24pXG4gKiBAcGFyYW0gZ2xvYmFsIC0gR2xvYmFsIG9iamVjdCBmb3IgZGVzZXJpYWxpemF0aW9uIGNvbnRleHRcbiAqIEBwYXJhbSBleHRyYVJldml2ZXJzIC0gQWRkaXRpb25hbCByZXZpdmVycyBmb3IgY3VzdG9tIHR5cGVzXG4gKiBAcmV0dXJucyBUaGUgaHlkcmF0ZWQgdGhyb3duIHZhbHVlLCByZWFkeSB0byByZWplY3QgdGhlIHN0ZXAgcHJvbWlzZVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaHlkcmF0ZVN0ZXBFcnJvcihcbiAgdmFsdWU6IFVpbnQ4QXJyYXkgfCB1bmtub3duLFxuICBfcnVuSWQ6IHN0cmluZyxcbiAga2V5OiBDcnlwdG9LZXkgfCB1bmRlZmluZWQsXG4gIGdsb2JhbDogUmVjb3JkPHN0cmluZywgYW55PiA9IGdsb2JhbFRoaXMsXG4gIGV4dHJhUmV2aXZlcnM6IFJlY29yZDxzdHJpbmcsICh2YWx1ZTogYW55KSA9PiBhbnk+ID0ge31cbik6IFByb21pc2U8dW5rbm93bj4ge1xuICBjb25zdCBjb21wcmVzc2lvblN0YXRzOiBDb21wcmVzc2lvblN0YXRzID0ge307XG4gIGNvbnN0IGRlY3J5cHRlZCA9IGF3YWl0IGRlY29tcHJlc3MoXG4gICAgYXdhaXQgbWF5YmVEZWNyeXB0KHZhbHVlLCBrZXkpLFxuICAgIGNvbXByZXNzaW9uU3RhdHNcbiAgKTtcbiAgYXdhaXQgcmVjb3JkQ29tcHJlc3Npb24oY29tcHJlc3Npb25TdGF0cywgJ2Rlc2VyaWFsaXplJyk7XG5cbiAgaWYgKCEoZGVjcnlwdGVkIGluc3RhbmNlb2YgVWludDhBcnJheSkpIHtcbiAgICAvLyBUcmVhdGVkIGFzIGEgZGV2YWx1ZSBcImZsYXR0ZW5lZFwiIGFycmF5LiBJbiBwcm9kdWN0aW9uIHRoaXMgYnJhbmNoIGlzXG4gICAgLy8gZXhlcmNpc2VkIGJ5IGxlZ2FjeSBjb2RlIHBhdGhzIHRoYXQgYnlwYXNzZWQgYGRlaHlkcmF0ZVN0ZXBFcnJvcmA7IHRoZVxuICAgIC8vIFNESyB2ZXJzaW9uIGlzIHBpbm5lZCBwZXIgd29ya2Zsb3cgcnVuIHZpYSBza2V3IHByb3RlY3Rpb24sIHNvIGFcbiAgICAvLyBjdXJyZW50LXZlcnNpb24gcHJvZHVjZXIgYWx3YXlzIGVtaXRzIGEgVWludDhBcnJheSBoZXJlLiBJZiBhXG4gICAgLy8gbWlzc2hhcGVuIHZhbHVlIHJlYWNoZXMgdXMsIGB1bmZsYXR0ZW5gIHRocm93cyDigJQgdGhhdCdzIGludGVudGlvbmFsOlxuICAgIC8vIHRoZSBoaWdoZXItbGV2ZWwgaHlkcmF0aW9uIGhlbHBlcnMgKGBoeWRyYXRlU3RlcElPYCxcbiAgICAvLyBgaHlkcmF0ZVJlc291cmNlSU9gKSBhbHJlYWR5IHdyYXAgdXMgaW4gYSB0cnkvY2F0Y2ggdGhhdCBsZWF2ZXMgdGhlXG4gICAgLy8gZmllbGQgdW4taHlkcmF0ZWQgZm9yIG8xMXkgZGlzcGxheSwgYW5kIHN1cmZhY2luZyB0aGUgdGhyb3cgdG8gbG9nc1xuICAgIC8vIGlzIG1vcmUgZGVidWdnYWJsZSB0aGFuIHNpbGVudGx5IG1hc2tpbmcgdGhlIHVuc3VwcG9ydGVkIHNoYXBlLlxuICAgIHJldHVybiB1bmZsYXR0ZW4oZGVjcnlwdGVkIGFzIGFueVtdLCB7XG4gICAgICAuLi5nZXRXb3JrZmxvd1Jldml2ZXJzKGdsb2JhbCksXG4gICAgICAuLi5leHRyYVJldml2ZXJzLFxuICAgIH0pO1xuICB9XG5cbiAgY29uc3QgeyBmb3JtYXQsIHBheWxvYWQgfSA9IGRlY29kZUZvcm1hdFByZWZpeChkZWNyeXB0ZWQpO1xuXG4gIGlmIChmb3JtYXQgPT09IFNlcmlhbGl6YXRpb25Gb3JtYXQuREVWQUxVRV9WMSkge1xuICAgIGNvbnN0IHN0ciA9IG5ldyBUZXh0RGVjb2RlcigpLmRlY29kZShwYXlsb2FkKTtcbiAgICByZXR1cm4gcGFyc2Uoc3RyLCB7XG4gICAgICAuLi5nZXRXb3JrZmxvd1Jldml2ZXJzKGdsb2JhbCksXG4gICAgICAuLi5leHRyYVJldml2ZXJzLFxuICAgIH0pO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBzZXJpYWxpemF0aW9uIGZvcm1hdDogJHtmb3JtYXR9YCk7XG59XG5cbi8qKlxuICogQ2FsbGVkIGZyb20gdGhlIHdvcmtmbG93IGhhbmRsZXIgd2hlbiB0aGUgd29ya2Zsb3cgaXRzZWxmIHRocm93cy5cbiAqIERlaHlkcmF0ZXMgdGhlIHRocm93biB2YWx1ZSBmcm9tIHdpdGhpbiB0aGUgd29ya2Zsb3cgZXhlY3V0aW9uIGVudmlyb25tZW50XG4gKiBpbnRvIGEgZm9ybWF0IHRoYXQgY2FuIGJlIHNhdmVkIHRvIHRoZSBkYXRhYmFzZSBpbiBhIGBydW5fZmFpbGVkYCBldmVudC5cbiAqXG4gKiBAcGFyYW0gdmFsdWUgLSBUaGUgdGhyb3duIHZhbHVlIHRvIHNlcmlhbGl6ZSAoY2FuIGJlIGFueSB0eXBlKVxuICogQHBhcmFtIHJ1bklkIC0gUnVuIElEIGZvciBlbmNyeXB0aW9uIGNvbnRleHRcbiAqIEBwYXJhbSBrZXkgLSBFbmNyeXB0aW9uIGtleSAodW5kZWZpbmVkIHRvIHNraXAgZW5jcnlwdGlvbilcbiAqIEBwYXJhbSBnbG9iYWwgLSBHbG9iYWwgb2JqZWN0IGZvciBzZXJpYWxpemF0aW9uIGNvbnRleHRcbiAqIEByZXR1cm5zIFRoZSBkZWh5ZHJhdGVkIHZhbHVlIGFzIGJpbmFyeSBkYXRhIChVaW50OEFycmF5KSB3aXRoIGZvcm1hdCBwcmVmaXhcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlaHlkcmF0ZVJ1bkVycm9yKFxuICB2YWx1ZTogdW5rbm93bixcbiAgX3J1bklkOiBzdHJpbmcsXG4gIGtleTogQ3J5cHRvS2V5IHwgdW5kZWZpbmVkLFxuICBnbG9iYWw6IFJlY29yZDxzdHJpbmcsIGFueT4gPSBnbG9iYWxUaGlzLFxuICBjb21wcmVzc2lvbiA9IGZhbHNlXG4pOiBQcm9taXNlPFVpbnQ4QXJyYXk+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCBzdHIgPSBzdHJpbmdpZnkodmFsdWUsIGdldFdvcmtmbG93UmVkdWNlcnMoZ2xvYmFsKSk7XG4gICAgY29uc3QgcGF5bG9hZCA9IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShzdHIpO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSBlbmNvZGVXaXRoRm9ybWF0UHJlZml4KFxuICAgICAgU2VyaWFsaXphdGlvbkZvcm1hdC5ERVZBTFVFX1YxLFxuICAgICAgcGF5bG9hZFxuICAgICkgYXMgVWludDhBcnJheTtcbiAgICAvLyBDb21wcmVzcyBiZWZvcmUgZW5jcnlwdGluZyDigJQgZW5jcnlwdGVkIGJ5dGVzIGRvbid0IGNvbXByZXNzLlxuICAgIGNvbnN0IGNvbXByZXNzaW9uU3RhdHM6IENvbXByZXNzaW9uU3RhdHMgPSB7fTtcbiAgICBjb25zdCBjb21wcmVzc2VkID0gYXdhaXQgY29tcHJlc3MoXG4gICAgICBzZXJpYWxpemVkLFxuICAgICAgY29tcHJlc3Npb24sXG4gICAgICBjb21wcmVzc2lvblN0YXRzXG4gICAgKTtcbiAgICBjb25zdCBlbmNyeXB0ZWQgPSAoYXdhaXQgbWF5YmVFbmNyeXB0KFxuICAgICAgY29tcHJlc3NlZCBhcyBVaW50OEFycmF5LFxuICAgICAga2V5XG4gICAgKSkgYXMgVWludDhBcnJheTtcbiAgICBhd2FpdCByZWNvcmRDb21wcmVzc2lvbihjb21wcmVzc2lvblN0YXRzLCAnc2VyaWFsaXplJyk7XG4gICAgcmV0dXJuIGVuY3J5cHRlZDtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBjb25zdCBjYXVzZSA9IHVud3JhcFNlcmlhbGl6YXRpb25DYXVzZShlcnJvcik7XG4gICAgY29uc3QgeyBtZXNzYWdlLCBoaW50IH0gPSBmb3JtYXRTZXJpYWxpemF0aW9uRXJyb3IoJ3J1biBlcnJvcicsIGNhdXNlKTtcbiAgICB0aHJvdyBuZXcgU2VyaWFsaXphdGlvbkVycm9yKG1lc3NhZ2UsIHsgaGludCwgY2F1c2UgfSk7XG4gIH1cbn1cblxuLyoqXG4gKiBDYWxsZWQgZnJvbSB0aGUgY2xpZW50IHNpZGUgKG9yIG9ic2VydmFiaWxpdHkgdG9vbHMpIHRvIGh5ZHJhdGUgdGhlIHJ1blxuICogZXJyb3IgdmFsdWUgb2YgYSBmYWlsZWQgd29ya2Zsb3cgcnVuLlxuICpcbiAqIEBwYXJhbSB2YWx1ZSAtIEJpbmFyeSBzZXJpYWxpemVkIGRhdGEgKFVpbnQ4QXJyYXkpIHdpdGggZm9ybWF0IHByZWZpeFxuICogQHBhcmFtIHJ1bklkIC0gUnVuIElEIGZvciBkZWNyeXB0aW9uIGNvbnRleHRcbiAqIEBwYXJhbSBrZXkgLSBFbmNyeXB0aW9uIGtleSAodW5kZWZpbmVkIHRvIHNraXAgZGVjcnlwdGlvbilcbiAqIEBwYXJhbSBvcHMgLSBQcm9taXNlIGFycmF5IGZvciBzdHJlYW0gb3BlcmF0aW9uc1xuICogQHBhcmFtIGdsb2JhbCAtIEdsb2JhbCBvYmplY3QgZm9yIGRlc2VyaWFsaXphdGlvbiBjb250ZXh0XG4gKiBAcGFyYW0gZXh0cmFSZXZpdmVycyAtIEFkZGl0aW9uYWwgcmV2aXZlcnMgZm9yIGN1c3RvbSB0eXBlc1xuICogQHJldHVybnMgVGhlIGh5ZHJhdGVkIHRocm93biB2YWx1ZSwgcmVhZHkgdG8gYmUgY29uc3VtZWQgYnkgdGhlIGNsaWVudFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaHlkcmF0ZVJ1bkVycm9yKFxuICB2YWx1ZTogVWludDhBcnJheSB8IHVua25vd24sXG4gIHJ1bklkOiBzdHJpbmcsXG4gIGtleTogQ3J5cHRvS2V5IHwgdW5kZWZpbmVkLFxuICBvcHM6IFByb21pc2U8dm9pZD5bXSA9IFtdLFxuICBnbG9iYWw6IFJlY29yZDxzdHJpbmcsIGFueT4gPSBnbG9iYWxUaGlzLFxuICBleHRyYVJldml2ZXJzOiBSZWNvcmQ8c3RyaW5nLCAodmFsdWU6IGFueSkgPT4gYW55PiA9IHt9XG4pOiBQcm9taXNlPHVua25vd24+IHtcbiAgY29uc3QgY29tcHJlc3Npb25TdGF0czogQ29tcHJlc3Npb25TdGF0cyA9IHt9O1xuICBjb25zdCBkZWNyeXB0ZWQgPSBhd2FpdCBkZWNvbXByZXNzKFxuICAgIGF3YWl0IG1heWJlRGVjcnlwdCh2YWx1ZSwga2V5KSxcbiAgICBjb21wcmVzc2lvblN0YXRzXG4gICk7XG4gIGF3YWl0IHJlY29yZENvbXByZXNzaW9uKGNvbXByZXNzaW9uU3RhdHMsICdkZXNlcmlhbGl6ZScpO1xuXG4gIGlmICghKGRlY3J5cHRlZCBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpKSB7XG4gICAgLy8gU2VlIHRoZSBtYXRjaGluZyBub3RlIGluIGBoeWRyYXRlU3RlcEVycm9yYDogdGhpcyBicmFuY2ggaXMgZm9yXG4gICAgLy8gZGV2YWx1ZSBmbGF0dGVuZWQgYXJyYXlzIGZyb20gbGVnYWN5IGNhbGxlcnM7IGN1cnJlbnQgU0RLIHZlcnNpb25zXG4gICAgLy8gYWx3YXlzIGVtaXQgYSBVaW50OEFycmF5LCBhbmQgYSBtaXNzaGFwZW4gdmFsdWUgaGVyZSBpbnRlbnRpb25hbGx5XG4gICAgLy8gdGhyb3dzIHZpYSBgdW5mbGF0dGVuYCBzbyB0aGUgc3Vycm91bmRpbmcgdHJ5L2NhdGNoIGluIG8xMXkgaGVscGVyc1xuICAgIC8vIHN1cmZhY2VzIHRoZSBpc3N1ZSByYXRoZXIgdGhhbiBtYXNraW5nIGl0LlxuICAgIHJldHVybiB1bmZsYXR0ZW4oZGVjcnlwdGVkIGFzIGFueVtdLCB7XG4gICAgICAuLi5nZXRFeHRlcm5hbFJldml2ZXJzKGdsb2JhbCwgb3BzLCBydW5JZCwga2V5KSxcbiAgICAgIC4uLmV4dHJhUmV2aXZlcnMsXG4gICAgfSk7XG4gIH1cblxuICBjb25zdCB7IGZvcm1hdCwgcGF5bG9hZCB9ID0gZGVjb2RlRm9ybWF0UHJlZml4KGRlY3J5cHRlZCk7XG5cbiAgaWYgKGZvcm1hdCA9PT0gU2VyaWFsaXphdGlvbkZvcm1hdC5ERVZBTFVFX1YxKSB7XG4gICAgY29uc3Qgc3RyID0gbmV3IFRleHREZWNvZGVyKCkuZGVjb2RlKHBheWxvYWQpO1xuICAgIHJldHVybiBwYXJzZShzdHIsIHtcbiAgICAgIC4uLmdldEV4dGVybmFsUmV2aXZlcnMoZ2xvYmFsLCBvcHMsIHJ1bklkLCBrZXkpLFxuICAgICAgLi4uZXh0cmFSZXZpdmVycyxcbiAgICB9KTtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgc2VyaWFsaXphdGlvbiBmb3JtYXQ6ICR7Zm9ybWF0fWApO1xufVxuXG4vKipcbiAqIENhbGxlZCBmcm9tIHRoZSB3b3JrZmxvdyBoYW5kbGVyIHdoZW4gcmVwbGF5aW5nIHRoZSBldmVudCBsb2cgb2YgYSBgc3RlcF9jb21wbGV0ZWRgIGV2ZW50LlxuICogSHlkcmF0ZXMgdGhlIHJldHVybiB2YWx1ZSBvZiBhIHN0ZXAgZnJvbSB0aGUgZGF0YWJhc2UuXG4gKlxuICogQHBhcmFtIHZhbHVlIC0gQmluYXJ5IHNlcmlhbGl6ZWQgZGF0YSAoVWludDhBcnJheSkgd2l0aCBmb3JtYXQgcHJlZml4XG4gKiBAcGFyYW0gcnVuSWQgLSBSdW4gSUQgZm9yIGRlY3J5cHRpb24gY29udGV4dFxuICogQHBhcmFtIGtleSAtIEVuY3J5cHRpb24ga2V5ICh1bmRlZmluZWQgdG8gc2tpcCBkZWNyeXB0aW9uKVxuICogQHBhcmFtIGdsb2JhbCAtIEdsb2JhbCBvYmplY3QgZm9yIGRlc2VyaWFsaXphdGlvbiBjb250ZXh0XG4gKiBAcGFyYW0gZXh0cmFSZXZpdmVycyAtIEFkZGl0aW9uYWwgcmV2aXZlcnMgZm9yIGN1c3RvbSB0eXBlc1xuICogQ2FsbGVkIGZyb20gdGhlIHdvcmtmbG93IGhhbmRsZXIgd2hlbiByZXBsYXlpbmcgdGhlIGV2ZW50IGxvZ1xuICogb2YgYSBgc3RlcF9jb21wbGV0ZWRgIGV2ZW50LlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaHlkcmF0ZVN0ZXBSZXR1cm5WYWx1ZShcbiAgdmFsdWU6IFVpbnQ4QXJyYXkgfCB1bmtub3duLFxuICBfcnVuSWQ6IHN0cmluZyxcbiAga2V5OiBDcnlwdG9LZXkgfCB1bmRlZmluZWQsXG4gIGdsb2JhbDogUmVjb3JkPHN0cmluZywgYW55PiA9IGdsb2JhbFRoaXMsXG4gIGV4dHJhUmV2aXZlcnM6IFJlY29yZDxzdHJpbmcsICh2YWx1ZTogYW55KSA9PiBhbnk+ID0ge31cbik6IFByb21pc2U8YW55PiB7XG4gIGNvbnN0IGNvbXByZXNzaW9uU3RhdHM6IENvbXByZXNzaW9uU3RhdHMgPSB7fTtcbiAgY29uc3QgaW5mbGF0ZWQgPSBhd2FpdCBkZWNvbXByZXNzKFxuICAgIGF3YWl0IG1heWJlRGVjcnlwdCh2YWx1ZSwga2V5KSxcbiAgICBjb21wcmVzc2lvblN0YXRzXG4gICk7XG4gIGF3YWl0IHJlY29yZENvbXByZXNzaW9uKGNvbXByZXNzaW9uU3RhdHMsICdkZXNlcmlhbGl6ZScpO1xuICByZXR1cm4gd29ya2Zsb3dNb2R1bGUuZGVzZXJpYWxpemUoaW5mbGF0ZWQsIHtcbiAgICBnbG9iYWwsXG4gICAgZXh0cmFSZXZpdmVyczoge1xuICAgICAgLi4uZ2V0U3RyZWFtQW5kUmVxdWVzdFJldml2ZXJzKGdldFdvcmtmbG93UmV2aXZlcnMoZ2xvYmFsKSksXG4gICAgICAuLi5leHRyYVJldml2ZXJzLFxuICAgIH0sXG4gIH0pO1xufVxuXG4vLyAtLS0tIEhlbHBlcnMgdG8gZXh0cmFjdCBzdHJlYW0vUmVxdWVzdC9SZXNwb25zZSByZWR1Y2VycyBhbmQgcmV2aXZlcnMgLS0tLVxuLy8gVGhlIG1vZGUtc3BlY2lmaWMgZ2V0KlJlZHVjZXJzL2dldCpSZXZpdmVycyBmdW5jdGlvbnMgcmV0dXJuIG9iamVjdHMgdGhhdFxuLy8gaW5jbHVkZSBib3RoIFwiY29tbW9uXCIgZW50cmllcyAoRGF0ZSwgRXJyb3IsIE1hcCwgZXRjLikgYW5kIG1vZGUtc3BlY2lmaWNcbi8vIGVudHJpZXMgKFJlYWRhYmxlU3RyZWFtLCBXcml0YWJsZVN0cmVhbSwgUmVxdWVzdCwgUmVzcG9uc2UsIFN0ZXBGdW5jdGlvbikuXG4vLyBUaGUgY29tbW9uIGVudHJpZXMgYXJlIGFscmVhZHkgY29tcG9zZWQgYnkgdGhlIGNvZGVjLiBXZSBvbmx5IG5lZWQgdG9cbi8vIHBhc3MgdGhyb3VnaCB0aGUgbW9kZS1zcGVjaWZpYyBlbnRyaWVzIGFzIGV4dHJhUmVkdWNlcnMvZXh0cmFSZXZpdmVycy5cblxuY29uc3QgU1RSRUFNX0FORF9SRVFVRVNUX0tFWVMgPSBbXG4gICdSZWFkYWJsZVN0cmVhbScsXG4gICdXcml0YWJsZVN0cmVhbScsXG4gICdSZXF1ZXN0JyxcbiAgJ1Jlc3BvbnNlJyxcbiAgJ1N0ZXBGdW5jdGlvbicsXG4gIC8vIFdpcmUgQWJvcnRDb250cm9sbGVyL0Fib3J0U2lnbmFsIHRocm91Z2ggdGhlIGNsaWVudCBzZXJpYWxpemF0aW9uIHBhdGggc29cbiAgLy8gc2lnbmFscyByZWFjaGFibGUgdmlhIFJlcXVlc3Quc2lnbmFsIChvciBhcyBkaXJlY3QgYXJndW1lbnRzKSBnZXQgdGhlaXJcbiAgLy8gZGVkaWNhdGVkIHJlZHVjZXIuIFdpdGhvdXQgdGhpcywgZGV2YWx1ZSBmYWxscyBiYWNrIHRvIGl0cyBhcmJpdHJhcnktUE9KT1xuICAvLyBwYXRoIGFuZCBmYWlscyBmb3IgYW55IHNpZ25hbCB0aGUgUmVxdWVzdCByZWR1Y2VyIGZvcndhcmRzLlxuICAnQWJvcnRDb250cm9sbGVyJyxcbiAgJ0Fib3J0U2lnbmFsJyxcbl0gYXMgY29uc3Q7XG5cbmZ1bmN0aW9uIGdldFN0cmVhbUFuZFJlcXVlc3RSZWR1Y2VycyhcbiAgYWxsUmVkdWNlcnM6IFJlY29yZDxzdHJpbmcsIGFueT5cbik6IFJlY29yZDxzdHJpbmcsICh2YWx1ZTogYW55KSA9PiBhbnk+IHtcbiAgY29uc3QgZXh0cmE6IFJlY29yZDxzdHJpbmcsICh2YWx1ZTogYW55KSA9PiBhbnk+ID0ge307XG4gIGZvciAoY29uc3Qga2V5IG9mIFNUUkVBTV9BTkRfUkVRVUVTVF9LRVlTKSB7XG4gICAgaWYgKGtleSBpbiBhbGxSZWR1Y2Vycykge1xuICAgICAgZXh0cmFba2V5XSA9IGFsbFJlZHVjZXJzW2tleV07XG4gICAgfVxuICB9XG4gIHJldHVybiBleHRyYTtcbn1cblxuZnVuY3Rpb24gZ2V0U3RyZWFtQW5kUmVxdWVzdFJldml2ZXJzKFxuICBhbGxSZXZpdmVyczogUmVjb3JkPHN0cmluZywgYW55PlxuKTogUmVjb3JkPHN0cmluZywgKHZhbHVlOiBhbnkpID0+IGFueT4ge1xuICBjb25zdCBleHRyYTogUmVjb3JkPHN0cmluZywgKHZhbHVlOiBhbnkpID0+IGFueT4gPSB7fTtcbiAgZm9yIChjb25zdCBrZXkgb2YgU1RSRUFNX0FORF9SRVFVRVNUX0tFWVMpIHtcbiAgICBpZiAoa2V5IGluIGFsbFJldml2ZXJzKSB7XG4gICAgICBleHRyYVtrZXldID0gYWxsUmV2aXZlcnNba2V5XTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGV4dHJhO1xufVxuIl19