footprintjs 9.26.0 → 9.28.0

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 (54) hide show
  1. package/AGENTS.md +3 -0
  2. package/CLAUDE.md +5 -4
  3. package/README.md +4 -0
  4. package/dist/advanced.js +3 -2
  5. package/dist/esm/advanced.d.ts +2 -2
  6. package/dist/esm/advanced.js +2 -2
  7. package/dist/esm/index.d.ts +1 -1
  8. package/dist/esm/index.js +1 -1
  9. package/dist/esm/lib/builder/FlowChartBuilder.d.ts +10 -0
  10. package/dist/esm/lib/builder/FlowChartBuilder.js +27 -13
  11. package/dist/esm/lib/engine/handlers/ChildrenExecutor.js +45 -12
  12. package/dist/esm/lib/engine/handlers/ResumeEntry.d.ts +195 -0
  13. package/dist/esm/lib/engine/handlers/ResumeEntry.js +471 -0
  14. package/dist/esm/lib/engine/handlers/SubflowExecutor.d.ts +6 -0
  15. package/dist/esm/lib/engine/handlers/SubflowExecutor.js +43 -10
  16. package/dist/esm/lib/engine/handlers/index.d.ts +2 -0
  17. package/dist/esm/lib/engine/handlers/index.js +2 -1
  18. package/dist/esm/lib/engine/narrative/CombinedNarrativeRecorder.d.ts +1 -1
  19. package/dist/esm/lib/engine/traversal/FlowchartTraverser.d.ts +49 -4
  20. package/dist/esm/lib/engine/traversal/FlowchartTraverser.js +64 -13
  21. package/dist/esm/lib/engine/types.d.ts +30 -11
  22. package/dist/esm/lib/engine/types.js +1 -1
  23. package/dist/esm/lib/pause/index.d.ts +1 -1
  24. package/dist/esm/lib/pause/index.js +1 -1
  25. package/dist/esm/lib/pause/types.d.ts +93 -5
  26. package/dist/esm/lib/pause/types.js +57 -3
  27. package/dist/esm/lib/runner/FlowChartExecutor.d.ts +8 -10
  28. package/dist/esm/lib/runner/FlowChartExecutor.js +153 -181
  29. package/dist/esm/lib/time-travel/bundles.js +11 -1
  30. package/dist/index.js +1 -1
  31. package/dist/lib/builder/FlowChartBuilder.js +27 -13
  32. package/dist/lib/engine/handlers/ChildrenExecutor.js +45 -12
  33. package/dist/lib/engine/handlers/ResumeEntry.js +478 -0
  34. package/dist/lib/engine/handlers/SubflowExecutor.js +43 -10
  35. package/dist/lib/engine/handlers/index.js +4 -2
  36. package/dist/lib/engine/traversal/FlowchartTraverser.js +64 -13
  37. package/dist/lib/engine/types.js +1 -1
  38. package/dist/lib/pause/index.js +1 -1
  39. package/dist/lib/pause/types.js +57 -3
  40. package/dist/lib/runner/FlowChartExecutor.js +153 -181
  41. package/dist/lib/time-travel/bundles.js +11 -1
  42. package/dist/types/advanced.d.ts +2 -2
  43. package/dist/types/index.d.ts +1 -1
  44. package/dist/types/lib/builder/FlowChartBuilder.d.ts +10 -0
  45. package/dist/types/lib/engine/handlers/ResumeEntry.d.ts +195 -0
  46. package/dist/types/lib/engine/handlers/SubflowExecutor.d.ts +6 -0
  47. package/dist/types/lib/engine/handlers/index.d.ts +2 -0
  48. package/dist/types/lib/engine/narrative/CombinedNarrativeRecorder.d.ts +1 -1
  49. package/dist/types/lib/engine/traversal/FlowchartTraverser.d.ts +49 -4
  50. package/dist/types/lib/engine/types.d.ts +30 -11
  51. package/dist/types/lib/pause/index.d.ts +1 -1
  52. package/dist/types/lib/pause/types.d.ts +93 -5
  53. package/dist/types/lib/runner/FlowChartExecutor.d.ts +8 -10
  54. package/package.json +1 -1
@@ -0,0 +1,478 @@
1
+ "use strict";
2
+ /**
3
+ * ResumeEntry — the resume's ONE-SHOT re-entry (M2, pause/resume).
4
+ *
5
+ * A resume has to get back to a stage in the middle of a chart. It does that
6
+ * with a small synthetic structure: a stand-in for the paused stage (the
7
+ * stage's own node with its function swapped for the resume half — or, for an
8
+ * `interrupt()` pause, for its own function with the answer deposited), and,
9
+ * for a pause inside subflows, the checkpoint's capture of each subflow's
10
+ * state on the way down.
11
+ *
12
+ * THE LAW: that structure is used EXACTLY ONCE, for the re-entry. The stand-in
13
+ * is where the resumed traversal STARTS (or where the leaf subflow's traversal
14
+ * starts) — it is never a node any id can resolve to. Each subflow on the pause
15
+ * path takes its seed and its entry point on its FIRST entry and never again.
16
+ * After that the run belongs to the real chart: every loop target, every later
17
+ * subflow entry (real root, inputMapper runs), every re-visit of the paused
18
+ * stage (which pauses again) resolves against the chart as built.
19
+ *
20
+ * ONE RULE AT EVERY LEVEL — what runs after the entry. On the original run,
21
+ * whatever DISPATCHED the paused stage (or the mount of the next subflow on
22
+ * the path) — a decider, a selector, a fork — ran its own continuation once
23
+ * that child's chain ended: the decider's `next`, the fork's join. A resume
24
+ * enters AT the child, so that continuation must be carried: the entry is
25
+ * the child with the enclosing dispatcher's continuation attached at the end
26
+ * of its own chain (`{ ...child, next: dispatcher.next }` for a chart the
27
+ * builder made). It is read from the CHART, level by level — never from the
28
+ * checkpoint, so an edited checkpoint cannot redirect a run — and it lands
29
+ * at the level it belongs to: a top-level decider's `next` runs at the top
30
+ * level, after the subflow's outputMapper, not inside the subflow.
31
+ *
32
+ * PARALLEL SIBLINGS THAT PAUSED TOO (9.28.0). When two children of one
33
+ * fan-out paused, the checkpoint asks the first and carries the others
34
+ * (`FlowchartCheckpoint.pendingPauses`). At that fan-out's level the entry is
35
+ * the child's own chain only — no join — and once it ends, the next sibling's
36
+ * pause is raised again as it was (its question, its captured state), without
37
+ * re-running anything. The join runs only when the last sibling is resumed.
38
+ *
39
+ * Before 9.28.0 the structure stayed in force for the whole resumed run — the
40
+ * traversal was ROOTED at the stand-in (so a loop back to the paused id re-ran
41
+ * the resume half, and a loop target upstream of the resume point was
42
+ * unreachable: one stage ran, then the run ended silently), and the leaf
43
+ * subflow's root was SWAPPED for the stand-in in the subflow dictionary (so a
44
+ * later entry into it would re-run the resume half on a stale seed).
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * // What FlowChartExecutor.resume() builds for a pause at 'sf-a/sf-b/ask'
49
+ * // (subflowPath ['sf-a', 'sf-a/sf-b']), 'sf-a/sf-b' mounted as a decider
50
+ * // branch inside sf-a whose decider continues to 'sf-a/after':
51
+ * const entry = ResumeEntry.plan({ root, subflows, path, captures, standIn });
52
+ * entry.start; // the top-level mount of 'sf-a'
53
+ * entry.enterSubflow('sf-a'); // { seed: sf-a's capture, entry: { ...mount of 'sf-a/sf-b', next: sf-a/after } }
54
+ * entry.enterSubflow('sf-a/sf-b'); // { seed: sf-b's capture, entry: the stand-in }
55
+ * entry.enterSubflow('sf-a/sf-b'); // undefined — a later entry is an ordinary one
56
+ * ```
57
+ *
58
+ * A pause two (or more) subflows deep therefore re-enters each outer subflow
59
+ * AT the mount of the next one — the outer subflow's stages before that mount
60
+ * do not run again (they did before 9.28.0). The one exception is a degraded
61
+ * checkpoint missing an outer subflow's capture: that subflow re-runs from its
62
+ * root with its inputMapper (its earlier stages recompute what the capture
63
+ * would have held), exactly as 9.27.0 did.
64
+ */
65
+ Object.defineProperty(exports, "__esModule", { value: true });
66
+ exports.findMount = exports.raiseQueuedPause = exports.queueBehind = exports.ResumeEntry = void 0;
67
+ const types_js_1 = require("../../pause/types.js");
68
+ class ResumeEntry {
69
+ /**
70
+ * Where the resumed TOP-LEVEL traversal starts: the stand-in (a top-level
71
+ * pause) or the mount of the first subflow on the path — each with its
72
+ * dispatcher's continuation attached. `undefined` for a seed-only entry —
73
+ * the traversal starts at its root.
74
+ */
75
+ start;
76
+ /** Sibling pauses whose fan-out sits at the TOP level — raised once `start`'s chain ends. */
77
+ startPendingPauses;
78
+ /**
79
+ * How many stage executions the resumed run makes before the stand-in runs
80
+ * — one per subflow on the path, each entered at its mount — so the
81
+ * executor's `onResume` names the stand-in's own `runtimeStageId`.
82
+ * `undefined` when it cannot be known before the run: an outer subflow
83
+ * missing its capture re-runs from its root.
84
+ */
85
+ stepsBeforeStandIn;
86
+ /** Hops not taken yet, by subflow id. A hop leaves this map when it is taken. */
87
+ pending;
88
+ constructor(start, hops, startPendingPauses, stepsBeforeStandIn) {
89
+ this.start = start;
90
+ this.startPendingPauses = startPendingPauses;
91
+ this.stepsBeforeStandIn = stepsBeforeStandIn;
92
+ this.pending = new Map(hops.map((hop) => [hop.subflowId, hop]));
93
+ }
94
+ /**
95
+ * Plan the re-entry of a paused chart. Every mount on the path, every
96
+ * dispatcher continuation and every waiting sibling is resolved HERE,
97
+ * against the chart as built, before a single stage runs — so a checkpoint
98
+ * whose path the chart cannot walk is refused up front instead of resuming
99
+ * into the wrong shape.
100
+ *
101
+ * @param args - `root` and `subflows`: the chart as built
102
+ * (`FlowChart.root`, `FlowChart.subflows`); `path`:
103
+ * `checkpoint.subflowPath`, outermost first; `captures`:
104
+ * `checkpoint.subflowStates` (a detached copy); `standIn`: the node that
105
+ * runs the resume half — the paused stage's own node, function swapped
106
+ * (its continuation is attached here); `pendingPauses`:
107
+ * `checkpoint.pendingPauses` (a detached copy).
108
+ * @throws when a subflow on the path is missing, mounted more than once, or
109
+ * its mount cannot be reached from the enclosing graph; or when a pending
110
+ * pause is malformed or is not a parallel sibling of the paused stage
111
+ */
112
+ static plan(args) {
113
+ const { root, subflows, path, captures, standIn } = args;
114
+ const chart = new ChartIndex();
115
+ // 1. Walk the path: the graph of every level, the mount of every subflow.
116
+ const graphs = [root];
117
+ const mounts = [];
118
+ for (let i = 0; i < path.length; i++) {
119
+ const subflowId = path[i];
120
+ mounts.push(chart.onlyMount(graphs[i], subflowId, i === 0 ? 'the flowchart' : `subflow '${path[i - 1]}'`));
121
+ // Own entries only: a path segment is data from a stored checkpoint,
122
+ // and `'__proto__'` must not resolve through the prototype chain.
123
+ const definition = ownEntry(subflows, subflowId);
124
+ if (!definition) {
125
+ throw new Error(`Cannot resume: subflow '${subflowId}' is not registered in the flowchart. ` +
126
+ 'The chart may have changed since the checkpoint was created.');
127
+ }
128
+ graphs.push(definition.root);
129
+ }
130
+ const leafLevel = path.length;
131
+ // The paused stage's REAL node — whose dispatcher the stand-in's
132
+ // continuation comes from. (The executor already found it; a direct
133
+ // caller's stand-in that is not in the leaf graph simply has none.)
134
+ const paused = chart.stage(graphs[leafLevel], standIn.id);
135
+ // 2. Queue every waiting sibling pause at the level of its fan-out.
136
+ const queues = queueSiblingPauses(args.pendingPauses, { chart, subflows, root, path, graphs, mounts, paused });
137
+ // 3. The one-shot entry of every level: the child, then its dispatcher's
138
+ // continuation — up to the fan-out when siblings wait there.
139
+ const childAt = (level) => (level < leafLevel ? mounts[level] : paused);
140
+ const entryAt = (level) => {
141
+ const child = childAt(level);
142
+ const replacement = level < leafLevel ? mounts[level] : standIn;
143
+ if (!child)
144
+ return replacement;
145
+ return chart.entry(graphs[level], child, replacement, queues[level]?.fanOut);
146
+ };
147
+ // 4. The hops. A subflow with no capture is entered at its ROOT with its
148
+ // inputMapper (its earlier stages recompute what the capture held) —
149
+ // except the leaf, whose entry is always the stand-in: re-running it
150
+ // from its root would ask again and lose the answer.
151
+ const hops = [];
152
+ let everyLevelAtItsEntry = true;
153
+ for (let i = 0; i < path.length; i++) {
154
+ const subflowId = path[i];
155
+ const seed = ownEntry(captures, subflowId);
156
+ const isLeafHop = i === path.length - 1;
157
+ if (seed === undefined && !isLeafHop) {
158
+ everyLevelAtItsEntry = false;
159
+ hops.push({ subflowId });
160
+ continue;
161
+ }
162
+ const waiting = queues[i + 1]?.pauses;
163
+ hops.push({
164
+ subflowId,
165
+ ...(seed !== undefined && { seed }),
166
+ entry: entryAt(i + 1),
167
+ ...(waiting && { pendingPauses: waiting }),
168
+ });
169
+ }
170
+ // Every level entered at its entry: one execution (the mount) per level
171
+ // runs before the stand-in.
172
+ return new ResumeEntry(entryAt(0), hops, queues[0]?.pauses, everyLevelAtItsEntry ? path.length : undefined);
173
+ }
174
+ /**
175
+ * A seed-only entry: each capture seeds the FIRST entry into its subflow,
176
+ * which then starts at its own root. What the deprecated
177
+ * `subflowStatesForResume` option (TraverserOptions / HandlerDeps) means
178
+ * since 9.28.0 — the same one-shot law, without a stand-in or a path.
179
+ */
180
+ static fromCaptures(captures) {
181
+ return new ResumeEntry(undefined, Object.entries(captures).map(([subflowId, seed]) => ({ subflowId, seed })));
182
+ }
183
+ /**
184
+ * The re-entry into `subflowId`, taken — or `undefined` when this entry is
185
+ * an ordinary one (the subflow is off the pause path, or its hop was already
186
+ * taken). ONE-SHOT: a hop is returned at most once, so a second entry into
187
+ * the same subflow (a loop passing its mount again) runs the real subflow
188
+ * from its real root with its inputMapper.
189
+ */
190
+ enterSubflow(subflowId) {
191
+ const hop = this.pending.get(subflowId);
192
+ if (hop !== undefined)
193
+ this.pending.delete(subflowId);
194
+ return hop;
195
+ }
196
+ /** `true` once every hop has been taken — the rest of the run is ordinary. */
197
+ get spent() {
198
+ return this.pending.size === 0;
199
+ }
200
+ }
201
+ exports.ResumeEntry = ResumeEntry;
202
+ // ── Raising a waiting sibling's pause ────────────────────────────────────────
203
+ /**
204
+ * Queue `queue` behind a pause passing through its level: a pause raised
205
+ * while siblings still wait must carry them to its checkpoint. Each path is
206
+ * cut to that level — the bubble-up prepends the levels above.
207
+ */
208
+ function queueBehind(signal, queue) {
209
+ for (const { pause, level } of queue) {
210
+ signal.addPendingPause({ ...pause, subflowPath: pause.subflowPath.slice(level) });
211
+ }
212
+ }
213
+ exports.queueBehind = queueBehind;
214
+ /**
215
+ * The first waiting sibling's pause, raised again at its fan-out's level —
216
+ * exactly as it bubbled up to that level the first time (its stage, its
217
+ * question, its own subflow captures), nothing re-run; the rest of the queue
218
+ * waits behind it. The subflows ABOVE the fan-out capture themselves afresh
219
+ * as it bubbles up, so they carry what the resumed child wrote.
220
+ */
221
+ function raiseQueuedPause(queue) {
222
+ const [first, ...rest] = queue;
223
+ const { pause, level } = first;
224
+ const signal = new types_js_1.PauseSignal(pause.pauseData, pause.pausedStageId, pause.pausedBy);
225
+ const below = pause.subflowPath.slice(level);
226
+ for (let i = below.length - 1; i >= 0; i--) {
227
+ const state = ownEntry(pause.subflowStates, below[i]);
228
+ if (state !== undefined)
229
+ signal.captureSubflowScope(below[i], state);
230
+ signal.prependSubflow(below[i]);
231
+ }
232
+ queueBehind(signal, rest);
233
+ return signal;
234
+ }
235
+ exports.raiseQueuedPause = raiseQueuedPause;
236
+ // ── Reading the chart ────────────────────────────────────────────────────────
237
+ /**
238
+ * The node that mounts `subflowId`, found by DFS from `start` over `next` and
239
+ * `children` (loop-ref stubs skipped — they share their target's id and carry
240
+ * nothing). Cycle-safe (visited by identity, so an absent id terminates too);
241
+ * first match in DFS pre-order (children before `next`, like the builder).
242
+ */
243
+ function findMount(start, subflowId) {
244
+ for (const node of dispatcherIndex(start).keys()) {
245
+ if (node.subflowId === subflowId)
246
+ return node;
247
+ }
248
+ return undefined;
249
+ }
250
+ exports.findMount = findMount;
251
+ /**
252
+ * Every real node of one level's graph, in DFS pre-order, mapped to the
253
+ * DISPATCHER whose child-chain holds it — the node whose `children` it
254
+ * descends from (a decider, a selector, a fork) — or `undefined` for a node
255
+ * on the level's own spine. Loop stubs are skipped; visited by identity, so
256
+ * two mounts sharing an id are both indexed and a cycle terminates.
257
+ */
258
+ function dispatcherIndex(root) {
259
+ const index = new Map();
260
+ const stack = [[root, undefined]];
261
+ for (let top = stack.pop(); top !== undefined; top = stack.pop()) {
262
+ const [node, dispatcher] = top;
263
+ if (node.isLoopRef || index.has(node))
264
+ continue;
265
+ index.set(node, dispatcher);
266
+ // LIFO: push `next` first and children reversed, so children are visited
267
+ // before `next` and the first child first — pre-order, like the builder.
268
+ if (node.next)
269
+ stack.push([node.next, dispatcher]);
270
+ if (node.children) {
271
+ for (let i = node.children.length - 1; i >= 0; i--)
272
+ stack.push([node.children[i], node]);
273
+ }
274
+ }
275
+ return index;
276
+ }
277
+ /** One plan's view of the chart: each level's index built once. */
278
+ class ChartIndex {
279
+ indexes = new Map();
280
+ of(root) {
281
+ let index = this.indexes.get(root);
282
+ if (!index) {
283
+ index = dispatcherIndex(root);
284
+ this.indexes.set(root, index);
285
+ }
286
+ return index;
287
+ }
288
+ /** Every mount of `subflowId` in `root`'s graph, in DFS pre-order. */
289
+ mountsOf(root, subflowId) {
290
+ return [...this.of(root).keys()].filter((node) => node.subflowId === subflowId);
291
+ }
292
+ /** The one mount of `subflowId` in `root`'s graph — refused when absent or ambiguous. */
293
+ onlyMount(root, subflowId, graphName) {
294
+ const found = this.mountsOf(root, subflowId);
295
+ if (found.length === 0) {
296
+ throw new Error(`Cannot resume: the mount of subflow '${subflowId}' is not reachable from ${graphName}. ` +
297
+ "The checkpoint's subflowPath does not match this chart — it may have changed since the checkpoint was created.");
298
+ }
299
+ if (found.length > 1) {
300
+ throw new Error(`Cannot resume: subflow '${subflowId}' is mounted more than once in ${graphName} ` +
301
+ `(${found.map((node) => `'${node.name}'`).join(', ')}), and a checkpoint's subflowPath cannot say which ` +
302
+ 'mount paused. Give each mount its own subflow id to make a pause inside it resumable.');
303
+ }
304
+ return found[0];
305
+ }
306
+ /** The real stage `id` in `root`'s graph (first in DFS pre-order), if any. */
307
+ stage(root, id) {
308
+ for (const node of this.of(root).keys())
309
+ if (node.id === id)
310
+ return node;
311
+ return undefined;
312
+ }
313
+ /** The dispatcher whose child-chain holds `node` in `root`'s graph (`undefined` on the spine). */
314
+ dispatcherOf(root, node) {
315
+ return this.of(root).get(node);
316
+ }
317
+ /**
318
+ * The one-shot entry for `child` (a mount on the path, or the paused stage)
319
+ * in `root`'s graph: `replacement` (the node that runs — the mount itself,
320
+ * or the stand-in) with what ran after `child`'s chain on the original run
321
+ * attached where that chain ends — `{ ...child, next: dispatcher.next }` for
322
+ * a chart the builder made:
323
+ *
324
+ * • on the level's spine: nothing to attach — the spine goes on by itself;
325
+ * • a DECIDER's or SELECTOR's branch: the dispatcher's `next`;
326
+ * • a FORK child: the fork's `next` — its join.
327
+ *
328
+ * Past a dispatcher with no `next`, the walk goes on OUTWARD to the one
329
+ * enclosing it. It stops at `stopAt` — the fan-out where siblings still
330
+ * wait, whose join must not run yet. Nothing to attach: `replacement`
331
+ * itself.
332
+ */
333
+ entry(root, child, replacement, stopAt) {
334
+ return appendAtChainEnd(replacement, this.after(root, child, stopAt));
335
+ }
336
+ /**
337
+ * What runs once `node`'s chain ends: its dispatcher's `next` chain, then —
338
+ * where THAT ends — the continuation of the dispatcher enclosing it, outward,
339
+ * up to `stopAt` (exclusive). `undefined` on the spine.
340
+ */
341
+ after(root, node, stopAt) {
342
+ const dispatcher = this.dispatcherOf(root, node);
343
+ if (dispatcher === undefined || dispatcher === stopAt)
344
+ return undefined;
345
+ const outer = this.after(root, dispatcher, stopAt);
346
+ return dispatcher.next ? appendAtChainEnd(dispatcher.next, outer) : outer;
347
+ }
348
+ }
349
+ /**
350
+ * `start`'s chain with `after` attached where it ends — the chain's nodes
351
+ * copied on the way (never registered anywhere: ids still resolve to the real
352
+ * nodes). A chain that ends in a loop stub (or loops back on itself) is
353
+ * returned as is: control leaves it through the loop, never "after" it.
354
+ */
355
+ function appendAtChainEnd(start, after) {
356
+ if (after === undefined)
357
+ return start;
358
+ const chain = [];
359
+ const seen = new Set();
360
+ for (let node = start; node !== undefined; node = node.next) {
361
+ if (node.isLoopRef || seen.has(node))
362
+ return start;
363
+ seen.add(node);
364
+ chain.push(node);
365
+ }
366
+ let next = after;
367
+ for (let i = chain.length - 1; i >= 0; i--)
368
+ next = { ...chain[i], next };
369
+ return next;
370
+ }
371
+ /**
372
+ * Validate `checkpoint.pendingPauses` (untrusted input) and queue each at the
373
+ * level of its fan-out: the depth where its path parts from the paused
374
+ * stage's. There, the paused stage's child (a mount on the path, or the stage
375
+ * itself) and the sibling's must both hang off ONE parallel dispatcher — a
376
+ * fork or a selector — or the record is not a sibling and the resume is
377
+ * refused rather than asked a question the chart could not have raised.
378
+ */
379
+ function queueSiblingPauses(pending, at) {
380
+ const queues = [];
381
+ if (pending === undefined)
382
+ return queues;
383
+ if (!Array.isArray(pending))
384
+ throw new Error('Invalid checkpoint: pendingPauses must be an array.');
385
+ const { chart, subflows, root, path, graphs, mounts, paused } = at;
386
+ const seen = new Set();
387
+ pending.forEach((raw, n) => {
388
+ const pause = validPendingPause(raw, n);
389
+ // One record per paused sibling: a repeat would ask the same question twice.
390
+ const key = JSON.stringify([pause.subflowPath, pause.pausedStageId]);
391
+ if (seen.has(key)) {
392
+ throw new Error(`Cannot resume: checkpoint.pendingPauses[${n}] ('${pause.pausedStageId}') repeats an earlier entry.`);
393
+ }
394
+ seen.add(key);
395
+ let level = 0;
396
+ while (level < path.length && level < pause.subflowPath.length && path[level] === pause.subflowPath[level])
397
+ level++;
398
+ const graph = graphs[level];
399
+ const ours = level < path.length ? mounts[level] : paused;
400
+ const theirMounts = level < pause.subflowPath.length ? chart.mountsOf(graph, pause.subflowPath[level]) : [];
401
+ const theirs = level < pause.subflowPath.length
402
+ ? theirMounts.length === 1
403
+ ? theirMounts[0]
404
+ : undefined
405
+ : chart.stage(graph, pause.pausedStageId);
406
+ const fanOut = ours ? chart.dispatcherOf(graph, ours) : undefined;
407
+ const isSibling = ours !== undefined &&
408
+ theirs !== undefined &&
409
+ ours !== theirs &&
410
+ fanOut !== undefined &&
411
+ chart.dispatcherOf(graph, theirs) === fanOut &&
412
+ !fanOut.deciderFn &&
413
+ (queues[level] === undefined || queues[level].fanOut === fanOut);
414
+ if (!isSibling || !walksToItsStage(chart, subflows, graph, pause, level)) {
415
+ throw new Error(`Cannot resume: checkpoint.pendingPauses[${n}] ('${pause.pausedStageId}') is not a parallel sibling of ` +
416
+ `the paused stage '${paused?.id ?? '?'}' in this chart — no fork or selector runs them both, or its ` +
417
+ 'path does not lead to that stage. The chart may have changed since the checkpoint was created.');
418
+ }
419
+ const leafRoot = pause.subflowPath.length === 0 ? root : ownEntry(subflows, pause.subflowPath[pause.subflowPath.length - 1])?.root;
420
+ const stageName = (leafRoot && chart.stage(leafRoot, pause.pausedStageId)?.name) ?? pause.pausedStageId;
421
+ const queue = (queues[level] ??= { fanOut: fanOut, pauses: [] });
422
+ queue.pauses.push({ pause, level, stageName });
423
+ });
424
+ return queues;
425
+ }
426
+ /**
427
+ * Whether a waiting sibling's WHOLE path below its fan-out walks this chart:
428
+ * every segment the only mount of its subflow in the enclosing graph, every
429
+ * subflow registered, and the paused stage in the last graph — checked at
430
+ * the FIRST resume, so a tampered record is refused up front, not when its
431
+ * turn comes.
432
+ */
433
+ function walksToItsStage(chart, subflows, fanOutGraph, pause, level) {
434
+ let graph = fanOutGraph;
435
+ for (let i = level; i < pause.subflowPath.length; i++) {
436
+ if (chart.mountsOf(graph, pause.subflowPath[i]).length !== 1)
437
+ return false;
438
+ const definition = ownEntry(subflows, pause.subflowPath[i]);
439
+ if (!definition)
440
+ return false;
441
+ graph = definition.root;
442
+ }
443
+ return chart.stage(graph, pause.pausedStageId) !== undefined;
444
+ }
445
+ /** One `pendingPauses` entry, checked field by field — it comes from stored, untrusted data. */
446
+ function validPendingPause(raw, n) {
447
+ const refuse = (what) => {
448
+ throw new Error(`Invalid checkpoint: pendingPauses[${n}] ${what}.`);
449
+ };
450
+ if (raw === null || typeof raw !== 'object' || Array.isArray(raw))
451
+ refuse('must be an object');
452
+ const record = raw;
453
+ if (typeof record.pausedStageId !== 'string' || record.pausedStageId === '') {
454
+ refuse('must name its paused stage (pausedStageId, a non-empty string)');
455
+ }
456
+ const subflowPath = record.subflowPath;
457
+ if (!Array.isArray(subflowPath) || !subflowPath.every((s) => typeof s === 'string')) {
458
+ refuse('must carry its subflowPath (an array of strings)');
459
+ }
460
+ const states = record.subflowStates;
461
+ if (states !== undefined && (states === null || typeof states !== 'object' || Array.isArray(states))) {
462
+ refuse('must carry its subflowStates as an object');
463
+ }
464
+ if (record.pausedBy !== undefined && record.pausedBy !== 'interrupt')
465
+ refuse("has an unknown pausedBy (only 'interrupt')");
466
+ return {
467
+ pausedStageId: record.pausedStageId,
468
+ subflowPath: subflowPath,
469
+ subflowStates: states ?? {},
470
+ ...(record.pauseData !== undefined && { pauseData: record.pauseData }),
471
+ ...(record.pausedBy === 'interrupt' && { pausedBy: 'interrupt' }),
472
+ };
473
+ }
474
+ /** `record[key]` only when it is the record's OWN property — never through the prototype chain. */
475
+ function ownEntry(record, key) {
476
+ return record && Object.prototype.hasOwnProperty.call(record, key) ? record[key] : undefined;
477
+ }
478
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUmVzdW1lRW50cnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL2VuZ2luZS9oYW5kbGVycy9SZXN1bWVFbnRyeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBOERHOzs7QUFHSCxtREFBbUQ7QUE4Q25ELE1BQWEsV0FBVztJQUN0Qjs7Ozs7T0FLRztJQUNNLEtBQUssQ0FBc0M7SUFDcEQsNkZBQTZGO0lBQ3BGLGtCQUFrQixDQUFxQztJQUNoRTs7Ozs7O09BTUc7SUFDTSxrQkFBa0IsQ0FBcUI7SUFDaEQsaUZBQWlGO0lBQ2hFLE9BQU8sQ0FBdUM7SUFFL0QsWUFDRSxLQUEwQyxFQUMxQyxJQUF3QyxFQUN4QyxrQkFBMkMsRUFDM0Msa0JBQTJCO1FBRTNCLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBQ25CLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxrQkFBa0IsQ0FBQztRQUM3QyxJQUFJLENBQUMsa0JBQWtCLEdBQUcsa0JBQWtCLENBQUM7UUFDN0MsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxTQUFTLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2xFLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7T0FpQkc7SUFDSCxNQUFNLENBQUMsSUFBSSxDQUFlLElBT3pCO1FBQ0MsTUFBTSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsR0FBRyxJQUFJLENBQUM7UUFDekQsTUFBTSxLQUFLLEdBQUcsSUFBSSxVQUFVLEVBQWdCLENBQUM7UUFFN0MsMEVBQTBFO1FBQzFFLE1BQU0sTUFBTSxH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Q3BDLElBQUksTUFBTSxLQUFLLFNBQVMsSUFBSSxDQUFDLE1BQU0sS0FBSyxJQUFJLElBQUksT0FBTyxNQUFNLEtBQUssUUFBUSxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ3JHLE1BQU0sQ0FBQywyQ0FBMkMsQ0FBQyxDQUFDO0lBQ3RELENBQUM7SUFDRCxJQUFJLE1BQU0sQ0FBQyxRQUFRLEtBQUssU0FBUyxJQUFJLE1BQU0sQ0FBQyxRQUFRLEtBQUssV0FBVztRQUNsRSxNQUFNLENBQUMsNENBQTRDLENBQUMsQ0FBQztJQUN2RCxPQUFPO1FBQ0wsYUFBYSxFQUFFLE1BQU0sQ0FBQyxhQUF1QjtRQUM3QyxXQUFXLEVBQUUsV0FBdUI7UUFDcEMsYUFBYSxFQUFHLE1BQThELElBQUksRUFBRTtRQUNwRixHQUFHLENBQUMsTUFBTSxDQUFDLFNBQVMsS0FBSyxTQUFTLElBQUksRUFBRSxTQUFTLEVBQUUsTUFBTSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ3RFLEdBQUcsQ0FBQyxNQUFNLENBQUMsUUFBUSxLQUFLLFdBQVcsSUFBSSxFQUFFLFFBQVEsRUFBRSxXQUFvQixFQUFFLENBQUM7S0FDM0UsQ0FBQztBQUNKLENBQUM7QUFFRCxtR0FBbUc7QUFDbkcsU0FBUyxRQUFRLENBQUksTUFBcUMsRUFBRSxHQUFXO0lBQ3JFLE9BQU8sTUFBTSxJQUFJLE1BQU0sQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBQy9GLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFJlc3VtZUVudHJ5IOKAlCB0aGUgcmVzdW1lJ3MgT05FLVNIT1QgcmUtZW50cnkgKE0yLCBwYXVzZS9yZXN1bWUpLlxuICpcbiAqIEEgcmVzdW1lIGhhcyB0byBnZXQgYmFjayB0byBhIHN0YWdlIGluIHRoZSBtaWRkbGUgb2YgYSBjaGFydC4gSXQgZG9lcyB0aGF0XG4gKiB3aXRoIGEgc21hbGwgc3ludGhldGljIHN0cnVjdHVyZTogYSBzdGFuZC1pbiBmb3IgdGhlIHBhdXNlZCBzdGFnZSAodGhlXG4gKiBzdGFnZSdzIG93biBub2RlIHdpdGggaXRzIGZ1bmN0aW9uIHN3YXBwZWQgZm9yIHRoZSByZXN1bWUgaGFsZiDigJQgb3IsIGZvciBhblxuICogYGludGVycnVwdCgpYCBwYXVzZSwgZm9yIGl0cyBvd24gZnVuY3Rpb24gd2l0aCB0aGUgYW5zd2VyIGRlcG9zaXRlZCksIGFuZCxcbiAqIGZvciBhIHBhdXNlIGluc2lkZSBzdWJmbG93cywgdGhlIGNoZWNrcG9pbnQncyBjYXB0dXJlIG9mIGVhY2ggc3ViZmxvdydzXG4gKiBzdGF0ZSBvbiB0aGUgd2F5IGRvd24uXG4gKlxuICogVEhFIExBVzogdGhhdCBzdHJ1Y3R1cmUgaXMgdXNlZCBFWEFDVExZIE9OQ0UsIGZvciB0aGUgcmUtZW50cnkuIFRoZSBzdGFuZC1pblxuICogaXMgd2hlcmUgdGhlIHJlc3VtZWQgdHJhdmVyc2FsIFNUQVJUUyAob3Igd2hlcmUgdGhlIGxlYWYgc3ViZmxvdydzIHRyYXZlcnNhbFxuICogc3RhcnRzKSDigJQgaXQgaXMgbmV2ZXIgYSBub2RlIGFueSBpZCBjYW4gcmVzb2x2ZSB0by4gRWFjaCBzdWJmbG93IG9uIHRoZSBwYXVzZVxuICogcGF0aCB0YWtlcyBpdHMgc2VlZCBhbmQgaXRzIGVudHJ5IHBvaW50IG9uIGl0cyBGSVJTVCBlbnRyeSBhbmQgbmV2ZXIgYWdhaW4uXG4gKiBBZnRlciB0aGF0IHRoZSBydW4gYmVsb25ncyB0byB0aGUgcmVhbCBjaGFydDogZXZlcnkgbG9vcCB0YXJnZXQsIGV2ZXJ5IGxhdGVyXG4gKiBzdWJmbG93IGVudHJ5IChyZWFsIHJvb3QsIGlucHV0TWFwcGVyIHJ1bnMpLCBldmVyeSByZS12aXNpdCBvZiB0aGUgcGF1c2VkXG4gKiBzdGFnZSAod2hpY2ggcGF1c2VzIGFnYWluKSByZXNvbHZlcyBhZ2FpbnN0IHRoZSBjaGFydCBhcyBidWlsdC5cbiAqXG4gKiBPTkUgUlVMRSBBVCBFVkVSWSBMRVZFTCDigJQgd2hhdCBydW5zIGFmdGVyIHRoZSBlbnRyeS4gT24gdGhlIG9yaWdpbmFsIHJ1bixcbiAqIHdoYXRldmVyIERJU1BBVENIRUQgdGhlIHBhdXNlZCBzdGFnZSAob3IgdGhlIG1vdW50IG9mIHRoZSBuZXh0IHN1YmZsb3cgb25cbiAqIHRoZSBwYXRoKSDigJQgYSBkZWNpZGVyLCBhIHNlbGVjdG9yLCBhIGZvcmsg4oCUIHJhbiBpdHMgb3duIGNvbnRpbnVhdGlvbiBvbmNlXG4gKiB0aGF0IGNoaWxkJ3MgY2hhaW4gZW5kZWQ6IHRoZSBkZWNpZGVyJ3MgYG5leHRgLCB0aGUgZm9yaydzIGpvaW4uIEEgcmVzdW1lXG4gKiBlbnRlcnMgQVQgdGhlIGNoaWxkLCBzbyB0aGF0IGNvbnRpbnVhdGlvbiBtdXN0IGJlIGNhcnJpZWQ6IHRoZSBlbnRyeSBpc1xuICogdGhlIGNoaWxkIHdpdGggdGhlIGVuY2xvc2luZyBkaXNwYXRjaGVyJ3MgY29udGludWF0aW9uIGF0dGFjaGVkIGF0IHRoZSBlbmRcbiAqIG9mIGl0cyBvd24gY2hhaW4gKGB7IC4uLmNoaWxkLCBuZXh0OiBkaXNwYXRjaGVyLm5leHQgfWAgZm9yIGEgY2hhcnQgdGhlXG4gKiBidWlsZGVyIG1hZGUpLiBJdCBpcyByZWFkIGZyb20gdGhlIENIQVJULCBsZXZlbCBieSBsZXZlbCDigJQgbmV2ZXIgZnJvbSB0aGVcbiAqIGNoZWNrcG9pbnQsIHNvIGFuIGVkaXRlZCBjaGVja3BvaW50IGNhbm5vdCByZWRpcmVjdCBhIHJ1biDigJQgYW5kIGl0IGxhbmRzXG4gKiBhdCB0aGUgbGV2ZWwgaXQgYmVsb25ncyB0bzogYSB0b3AtbGV2ZWwgZGVjaWRlcidzIGBuZXh0YCBydW5zIGF0IHRoZSB0b3BcbiAqIGxldmVsLCBhZnRlciB0aGUgc3ViZmxvdydzIG91dHB1dE1hcHBlciwgbm90IGluc2lkZSB0aGUgc3ViZmxvdy5cbiAqXG4gKiBQQVJBTExFTCBTSUJMSU5HUyBUSEFUIFBBVVNFRCBUT08gKDkuMjguMCkuIFdoZW4gdHdvIGNoaWxkcmVuIG9mIG9uZVxuICogZmFuLW91dCBwYXVzZWQsIHRoZSBjaGVja3BvaW50IGFza3MgdGhlIGZpcnN0IGFuZCBjYXJyaWVzIHRoZSBvdGhlcnNcbiAqIChgRmxvd2NoYXJ0Q2hlY2twb2ludC5wZW5kaW5nUGF1c2VzYCkuIEF0IHRoYXQgZmFuLW91dCdzIGxldmVsIHRoZSBlbnRyeSBpc1xuICogdGhlIGNoaWxkJ3Mgb3duIGNoYWluIG9ubHkg4oCUIG5vIGpvaW4g4oCUIGFuZCBvbmNlIGl0IGVuZHMsIHRoZSBuZXh0IHNpYmxpbmcnc1xuICogcGF1c2UgaXMgcmFpc2VkIGFnYWluIGFzIGl0IHdhcyAoaXRzIHF1ZXN0aW9uLCBpdHMgY2FwdHVyZWQgc3RhdGUpLCB3aXRob3V0XG4gKiByZS1ydW5uaW5nIGFueXRoaW5nLiBUaGUgam9pbiBydW5zIG9ubHkgd2hlbiB0aGUgbGFzdCBzaWJsaW5nIGlzIHJlc3VtZWQuXG4gKlxuICogQmVmb3JlIDkuMjguMCB0aGUgc3RydWN0dXJlIHN0YXllZCBpbiBmb3JjZSBmb3IgdGhlIHdob2xlIHJlc3VtZWQgcnVuIOKAlCB0aGVcbiAqIHRyYXZlcnNhbCB3YXMgUk9PVEVEIGF0IHRoZSBzdGFuZC1pbiAoc28gYSBsb29wIGJhY2sgdG8gdGhlIHBhdXNlZCBpZCByZS1yYW5cbiAqIHRoZSByZXN1bWUgaGFsZiwgYW5kIGEgbG9vcCB0YXJnZXQgdXBzdHJlYW0gb2YgdGhlIHJlc3VtZSBwb2ludCB3YXNcbiAqIHVucmVhY2hhYmxlOiBvbmUgc3RhZ2UgcmFuLCB0aGVuIHRoZSBydW4gZW5kZWQgc2lsZW50bHkpLCBhbmQgdGhlIGxlYWZcbiAqIHN1YmZsb3cncyByb290IHdhcyBTV0FQUEVEIGZvciB0aGUgc3RhbmQtaW4gaW4gdGhlIHN1YmZsb3cgZGljdGlvbmFyeSAoc28gYVxuICogbGF0ZXIgZW50cnkgaW50byBpdCB3b3VsZCByZS1ydW4gdGhlIHJlc3VtZSBoYWxmIG9uIGEgc3RhbGUgc2VlZCkuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIFdoYXQgRmxvd0NoYXJ0RXhlY3V0b3IucmVzdW1lKCkgYnVpbGRzIGZvciBhIHBhdXNlIGF0ICdzZi1hL3NmLWIvYXNrJ1xuICogLy8gKHN1YmZsb3dQYXRoIFsnc2YtYScsICdzZi1hL3NmLWInXSksICdzZi1hL3NmLWInIG1vdW50ZWQgYXMgYSBkZWNpZGVyXG4gKiAvLyBicmFuY2ggaW5zaWRlIHNmLWEgd2hvc2UgZGVjaWRlciBjb250aW51ZXMgdG8gJ3NmLWEvYWZ0ZXInOlxuICogY29uc3QgZW50cnkgPSBSZXN1bWVFbnRyeS5wbGFuKHsgcm9vdCwgc3ViZmxvd3MsIHBhdGgsIGNhcHR1cmVzLCBzdGFuZEluIH0pO1xuICogZW50cnkuc3RhcnQ7ICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIHRvcC1sZXZlbCBtb3VudCBvZiAnc2YtYSdcbiAqIGVudHJ5LmVudGVyU3ViZmxvdygnc2YtYScpOyAgICAgIC8vIHsgc2VlZDogc2YtYSdzIGNhcHR1cmUsIGVudHJ5OiB7IC4uLm1vdW50IG9mICdzZi1hL3NmLWInLCBuZXh0OiBzZi1hL2FmdGVyIH0gfVxuICogZW50cnkuZW50ZXJTdWJmbG93KCdzZi1hL3NmLWInKTsgLy8geyBzZWVkOiBzZi1iJ3MgY2FwdHVyZSwgZW50cnk6IHRoZSBzdGFuZC1pbiB9XG4gKiBlbnRyeS5lbnRlclN1YmZsb3coJ3NmLWEvc2YtYicpOyAvLyB1bmRlZmluZWQg4oCUIGEgbGF0ZXIgZW50cnkgaXMgYW4gb3JkaW5hcnkgb25lXG4gKiBgYGBcbiAqXG4gKiBBIHBhdXNlIHR3byAob3IgbW9yZSkgc3ViZmxvd3MgZGVlcCB0aGVyZWZvcmUgcmUtZW50ZXJzIGVhY2ggb3V0ZXIgc3ViZmxvd1xuICogQVQgdGhlIG1vdW50IG9mIHRoZSBuZXh0IG9uZSDigJQgdGhlIG91dGVyIHN1YmZsb3cncyBzdGFnZXMgYmVmb3JlIHRoYXQgbW91bnRcbiAqIGRvIG5vdCBydW4gYWdhaW4gKHRoZXkgZGlkIGJlZm9yZSA5LjI4LjApLiBUaGUgb25lIGV4Y2VwdGlvbiBpcyBhIGRlZ3JhZGVkXG4gKiBjaGVja3BvaW50IG1pc3NpbmcgYW4gb3V0ZXIgc3ViZmxvdydzIGNhcHR1cmU6IHRoYXQgc3ViZmxvdyByZS1ydW5zIGZyb20gaXRzXG4gKiByb290IHdpdGggaXRzIGlucHV0TWFwcGVyIChpdHMgZWFybGllciBzdGFnZXMgcmVjb21wdXRlIHdoYXQgdGhlIGNhcHR1cmVcbiAqIHdvdWxkIGhhdmUgaGVsZCksIGV4YWN0bHkgYXMgOS4yNy4wIGRpZC5cbiAqL1xuXG5pbXBvcnQgdHlwZSB7IFBlbmRpbmdQYXVzZSB9IGZyb20gJy4uLy4uL3BhdXNlL3R5cGVzLmpzJztcbmltcG9ydCB7IFBhdXNlU2lnbmFsIH0gZnJvbSAnLi4vLi4vcGF1c2UvdHlwZXMuanMnO1xuaW1wb3J0IHR5cGUgeyBTdGFnZU5vZGUgfSBmcm9tICcuLi9ncmFwaC9TdGFnZU5vZGUuanMnO1xuXG4vKipcbiAqIEEgcGFyYWxsZWwgc2libGluZydzIHBhdXNlLCBxdWV1ZWQgYXQgdGhlIGxldmVsIG9mIGl0cyBmYW4tb3V0OiByYWlzZWRcbiAqIGFnYWluIHRoZXJlIG9uY2UgdGhlIHJlc3VtZWQgY2hpbGQncyBjaGFpbiBlbmRzIChzZWUge0BsaW5rIHJhaXNlUXVldWVkUGF1c2V9KS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBRdWV1ZWRQYXVzZSB7XG4gIC8qKiBUaGUgc2libGluZydzIHBhdXNlIGFzIHRoZSBjaGVja3BvaW50IGNhcnJpZXMgaXQg4oCUIGl0cyBwYXRoIGZyb20gdGhlIHRvcC4gKi9cbiAgcmVhZG9ubHkgcGF1c2U6IFBlbmRpbmdQYXVzZTtcbiAgLyoqIEhvdyBtYW55IHN1YmZsb3dzIGRlZXAgdGhlIGZhbi1vdXQgc2l0cyAoMCA9IHRoZSB0b3AgbGV2ZWwpLiAqL1xuICByZWFkb25seSBsZXZlbDogbnVtYmVyO1xuICAvKiogVGhlIHNpYmxpbmcncyBwYXVzZWQgc3RhZ2UncyBuYW1lLCBmb3IgdGhlIGBvblBhdXNlYCBldmVudC4gKi9cbiAgcmVhZG9ubHkgc3RhZ2VOYW1lOiBzdHJpbmc7XG59XG5cbi8qKiBPbmUgc3ViZmxvdyBib3VuZGFyeSBvbiB0aGUgd2F5IGJhY2sgdG8gYSBwYXVzZWQgc3RhZ2UuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlc3VtZUhvcDxUT3V0ID0gYW55LCBUU2NvcGUgPSBhbnk+IHtcbiAgLyoqIFRoZSBwYXRoLXByZWZpeGVkIHN1YmZsb3cgaWQgKGEgYEZsb3djaGFydENoZWNrcG9pbnQuc3ViZmxvd1BhdGhgIGVudHJ5KS4gKi9cbiAgcmVhZG9ubHkgc3ViZmxvd0lkOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgc3ViZmxvdydzIHN0YXRlIGF0IHRoZSBwYXVzZSAoYGNoZWNrcG9pbnQuc3ViZmxvd1N0YXRlc1tzdWJmbG93SWRdYCkuXG4gICAqIFNlZWRzIHRoZSBuZXN0ZWQgcnVudGltZSBJTlNURUFEIG9mIHRoZSBpbnB1dE1hcHBlcidzIHZhbHVlcyDigJQgdGhlIGNhcHR1cmVcbiAgICogYWxyZWFkeSBob2xkcyB0aGUgcG9zdC1pbnB1dCwgcHJlLXBhdXNlIG1lbW9yeSAodGhlIGlucHV0TWFwcGVyIHN0aWxsXG4gICAqIHJ1bnMsIGZvciB0aGUgc3RhZ2VzJyByZWFkLW9ubHkgYXJncyBvbmx5KS4gQWJzZW50IHdoZW4gdGhlIGNoZWNrcG9pbnRcbiAgICogaG9sZHMgbm8gY2FwdHVyZSBmb3IgdGhpcyBzdWJmbG93OyB0aGUgaW5wdXRNYXBwZXIgdGhlbiBzZWVkcyBpdCwgYXMgb25cbiAgICogYW55IGVudHJ5LlxuICAgKi9cbiAgcmVhZG9ubHkgc2VlZD86IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAvKipcbiAgICogV2hlcmUgdGhpcyBzdWJmbG93J3MgdHJhdmVyc2FsIHN0YXJ0cyBvbiB0aGUgcmUtZW50cnk6IHRoZSBtb3VudCBvZiB0aGVcbiAgICogbmV4dCBzdWJmbG93IG9uIHRoZSBwYXRoLCBvciDigJQgb24gdGhlIGxhc3QgaG9wIOKAlCB0aGUgcGF1c2VkIHN0YWdlJ3NcbiAgICogc3RhbmQtaW4sIGVhY2ggd2l0aCBpdHMgZGlzcGF0Y2hlcidzIGNvbnRpbnVhdGlvbiBhdHRhY2hlZCAoc2VlIHRoZVxuICAgKiBtb2R1bGUgZG9jKS4gQWJzZW50OiB0aGUgc3ViZmxvdydzIG93biByb290IOKAlCBhIHNlZWQtb25seSBob3AgKHNlZVxuICAgKiB7QGxpbmsgUmVzdW1lRW50cnkuZnJvbUNhcHR1cmVzfSksIG9yIGFuIG91dGVyIHN1YmZsb3cgd2hvc2UgY2FwdHVyZSB0aGVcbiAgICogY2hlY2twb2ludCBsYWNrcy5cbiAgICovXG4gIHJlYWRvbmx5IGVudHJ5PzogU3RhZ2VOb2RlPFRPdXQsIFRTY29wZT47XG4gIC8qKlxuICAgKiBQYXVzZXMgb2YgcGFyYWxsZWwgc2libGluZ3Mgd2hvc2UgZmFuLW91dCBzaXRzIGluIFRISVMgc3ViZmxvdywgcmFpc2VkIGluXG4gICAqIG9yZGVyIG9uY2UgYGVudHJ5YCdzIGNoYWluIGVuZHMgKHRoZSBmaXJzdCBpcyByYWlzZWQsIHRoZSByZXN0IHdhaXRcbiAgICogYmVoaW5kIGl0KS4gQWJzZW50IHdoZW4gbm8gc2libGluZyBpcyB3YWl0aW5nIGhlcmUuXG4gICAqL1xuICByZWFkb25seSBwZW5kaW5nUGF1c2VzPzogcmVhZG9ubHkgUXVldWVkUGF1c2VbXTtcbn1cblxuZXhwb3J0IGNsYXNzIFJlc3VtZUVudHJ5PFRPdXQgPSBhbnksIFRTY29wZSA9IGFueT4ge1xuICAvKipcbiAgICogV2hlcmUgdGhlIHJlc3VtZWQgVE9QLUxFVkVMIHRyYXZlcnNhbCBzdGFydHM6IHRoZSBzdGFuZC1pbiAoYSB0b3AtbGV2ZWxcbiAgICogcGF1c2UpIG9yIHRoZSBtb3VudCBvZiB0aGUgZmlyc3Qgc3ViZmxvdyBvbiB0aGUgcGF0aCDigJQgZWFjaCB3aXRoIGl0c1xuICAgKiBkaXNwYXRjaGVyJ3MgY29udGludWF0aW9uIGF0dGFjaGVkLiBgdW5kZWZpbmVkYCBmb3IgYSBzZWVkLW9ubHkgZW50cnkg4oCUXG4gICAqIHRoZSB0cmF2ZXJzYWwgc3RhcnRzIGF0IGl0cyByb290LlxuICAgKi9cbiAgcmVhZG9ubHkgc3RhcnQ6IFN0YWdlTm9kZTxUT3V0LCBUU2NvcGU+IHwgdW5kZWZpbmVkO1xuICAvKiogU2libGluZyBwYXVzZXMgd2hvc2UgZmFuLW91dCBzaXRzIGF0IHRoZSBUT1AgbGV2ZWwg4oCUIHJhaXNlZCBvbmNlIGBzdGFydGAncyBjaGFpbiBlbmRzLiAqL1xuICByZWFkb25seSBzdGFydFBlbmRpbmdQYXVzZXM6IHJlYWRvbmx5IFF1ZXVlZFBhdXNlW10gfCB1bmRlZmluZWQ7XG4gIC8qKlxuICAgKiBIb3cgbWFueSBzdGFnZSBleGVjdXRpb25zIHRoZSByZXN1bWVkIHJ1biBtYWtlcyBiZWZvcmUgdGhlIHN0YW5kLWluIHJ1bnNcbiAgICog4oCUIG9uZSBwZXIgc3ViZmxvdyBvbiB0aGUgcGF0aCwgZWFjaCBlbnRlcmVkIGF0IGl0cyBtb3VudCDigJQgc28gdGhlXG4gICAqIGV4ZWN1dG9yJ3MgYG9uUmVzdW1lYCBuYW1lcyB0aGUgc3RhbmQtaW4ncyBvd24gYHJ1bnRpbWVTdGFnZUlkYC5cbiAgICogYHVuZGVmaW5lZGAgd2hlbiBpdCBjYW5ub3QgYmUga25vd24gYmVmb3JlIHRoZSBydW46IGFuIG91dGVyIHN1YmZsb3dcbiAgICogbWlzc2luZyBpdHMgY2FwdHVyZSByZS1ydW5zIGZyb20gaXRzIHJvb3QuXG4gICAqL1xuICByZWFkb25seSBzdGVwc0JlZm9yZVN0YW5kSW46IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgLyoqIEhvcHMgbm90IHRha2VuIHlldCwgYnkgc3ViZmxvdyBpZC4gQSBob3AgbGVhdmVzIHRoaXMgbWFwIHdoZW4gaXQgaXMgdGFrZW4uICovXG4gIHByaXZhdGUgcmVhZG9ubHkgcGVuZGluZzogTWFwPHN0cmluZywgUmVzdW1lSG9wPFRPdXQsIFRTY29wZT4+O1xuXG4gIHByaXZhdGUgY29uc3RydWN0b3IoXG4gICAgc3RhcnQ6IFN0YWdlTm9kZTxUT3V0LCBUU2NvcGU+IHwgdW5kZWZpbmVkLFxuICAgIGhvcHM6IHJlYWRvbmx5IFJlc3VtZUhvcDxUT3V0LCBUU2NvcGU+W10sXG4gICAgc3RhcnRQZW5kaW5nUGF1c2VzPzogcmVhZG9ubHkgUXVldWVkUGF1c2VbXSxcbiAgICBzdGVwc0JlZm9yZVN0YW5kSW4/OiBudW1iZXIsXG4gICkge1xuICAgIHRoaXMuc3RhcnQgPSBzdGFydDtcbiAgICB0aGlzLnN0YXJ0UGVuZGluZ1BhdXNlcyA9IHN0YXJ0UGVuZGluZ1BhdXNlcztcbiAgICB0aGlzLnN0ZXBzQmVmb3JlU3RhbmRJbiA9IHN0ZXBzQmVmb3JlU3RhbmRJbjtcbiAgICB0aGlzLnBlbmRpbmcgPSBuZXcgTWFwKGhvcHMubWFwKChob3ApID0+IFtob3Auc3ViZmxvd0lkLCBob3BdKSk7XG4gIH1cblxuICAvKipcbiAgICogUGxhbiB0aGUgcmUtZW50cnkgb2YgYSBwYXVzZWQgY2hhcnQuIEV2ZXJ5IG1vdW50IG9uIHRoZSBwYXRoLCBldmVyeVxuICAgKiBkaXNwYXRjaGVyIGNvbnRpbnVhdGlvbiBhbmQgZXZlcnkgd2FpdGluZyBzaWJsaW5nIGlzIHJlc29sdmVkIEhFUkUsXG4gICAqIGFnYWluc3QgdGhlIGNoYXJ0IGFzIGJ1aWx0LCBiZWZvcmUgYSBzaW5nbGUgc3RhZ2UgcnVucyDigJQgc28gYSBjaGVja3BvaW50XG4gICAqIHdob3NlIHBhdGggdGhlIGNoYXJ0IGNhbm5vdCB3YWxrIGlzIHJlZnVzZWQgdXAgZnJvbnQgaW5zdGVhZCBvZiByZXN1bWluZ1xuICAgKiBpbnRvIHRoZSB3cm9uZyBzaGFwZS5cbiAgICpcbiAgICogQHBhcmFtIGFyZ3MgLSBgcm9vdGAgYW5kIGBzdWJmbG93c2A6IHRoZSBjaGFydCBhcyBidWlsdFxuICAgKiAgIChgRmxvd0NoYXJ0LnJvb3RgLCBgRmxvd0NoYXJ0LnN1YmZsb3dzYCk7IGBwYXRoYDpcbiAgICogICBgY2hlY2twb2ludC5zdWJmbG93UGF0aGAsIG91dGVybW9zdCBmaXJzdDsgYGNhcHR1cmVzYDpcbiAgICogICBgY2hlY2twb2ludC5zdWJmbG93U3RhdGVzYCAoYSBkZXRhY2hlZCBjb3B5KTsgYHN0YW5kSW5gOiB0aGUgbm9kZSB0aGF0XG4gICAqICAgcnVucyB0aGUgcmVzdW1lIGhhbGYg4oCUIHRoZSBwYXVzZWQgc3RhZ2UncyBvd24gbm9kZSwgZnVuY3Rpb24gc3dhcHBlZFxuICAgKiAgIChpdHMgY29udGludWF0aW9uIGlzIGF0dGFjaGVkIGhlcmUpOyBgcGVuZGluZ1BhdXNlc2A6XG4gICAqICAgYGNoZWNrcG9pbnQucGVuZGluZ1BhdXNlc2AgKGEgZGV0YWNoZWQgY29weSkuXG4gICAqIEB0aHJvd3Mgd2hlbiBhIHN1YmZsb3cgb24gdGhlIHBhdGggaXMgbWlzc2luZywgbW91bnRlZCBtb3JlIHRoYW4gb25jZSwgb3JcbiAgICogICBpdHMgbW91bnQgY2Fubm90IGJlIHJlYWNoZWQgZnJvbSB0aGUgZW5jbG9zaW5nIGdyYXBoOyBvciB3aGVuIGEgcGVuZGluZ1xuICAgKiAgIHBhdXNlIGlzIG1hbGZvcm1lZCBvciBpcyBub3QgYSBwYXJhbGxlbCBzaWJsaW5nIG9mIHRoZSBwYXVzZWQgc3RhZ2VcbiAgICovXG4gIHN0YXRpYyBwbGFuPFRPdXQsIFRTY29wZT4oYXJnczoge1xuICAgIHJvb3Q6IFN0YWdlTm9kZTxUT3V0LCBUU2NvcGU+O1xuICAgIHN1YmZsb3dzOiBSZWNvcmQ8c3RyaW5nLCB7IHJvb3Q6IFN0YWdlTm9kZTxUT3V0LCBUU2NvcGU+IH0+IHwgdW5kZWZpbmVkO1xuICAgIHBhdGg6IHJlYWRvbmx5IHN0cmluZ1tdO1xuICAgIGNhcHR1cmVzOiBSZWNvcmQ8c3RyaW5nLCBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4gfCB1bmRlZmluZWQ7XG4gICAgc3RhbmRJbjogU3RhZ2VOb2RlPFRPdXQsIFRTY29wZT47XG4gICAgcGVuZGluZ1BhdXNlcz86IHJlYWRvbmx5IFBlbmRpbmdQYXVzZVtdO1xuICB9KTogUmVzdW1lRW50cnk8VE91dCwgVFNjb3BlPiB7XG4gICAgY29uc3QgeyByb290LCBzdWJmbG93cywgcGF0aCwgY2FwdHVyZXMsIHN0YW5kSW4gfSA9IGFyZ3M7XG4gICAgY29uc3QgY2hhcnQgPSBuZXcgQ2hhcnRJbmRleDxUT3V0LCBUU2NvcGU+KCk7XG5cbiAgICAvLyAxLiBXYWxrIHRoZSBwYXRoOiB0aGUgZ3JhcGggb2YgZXZlcnkgbGV2ZWwsIHRoZSBtb3VudCBvZiBldmVyeSBzdWJmbG93LlxuICAgIGNvbnN0IGdyYXBoczogU3RhZ2VOb2RlPFRPdXQsIFRTY29wZT5bXSA9IFtyb290XTtcbiAgICBjb25zdCBtb3VudHM6IFN0YWdlTm9kZTxUT3V0LCBUU2NvcGU+W10gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBhdGgubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IHN1YmZsb3dJZCA9IHBhdGhbaV07XG4gICAgICBtb3VudHMucHVzaChjaGFydC5vbmx5TW91bnQoZ3JhcGhzW2ldLCBzdWJmbG93SWQsIGkgPT09IDAgPyAndGhlIGZsb3djaGFydCcgOiBgc3ViZmxvdyAnJHtwYXRoW2kgLSAxXX0nYCkpO1xuICAgICAgLy8gT3duIGVudHJpZXMgb25seTogYSBwYXRoIHNlZ21lbnQgaXMgZGF0YSBmcm9tIGEgc3RvcmVkIGNoZWNrcG9pbnQsXG4gICAgICAvLyBhbmQgYCdfX3Byb3RvX18nYCBtdXN0IG5vdCByZXNvbHZlIHRocm91Z2ggdGhlIHByb3RvdHlwZSBjaGFpbi5cbiAgICAgIGNvbnN0IGRlZmluaXRpb24gPSBvd25FbnRyeShzdWJmbG93cywgc3ViZmxvd0lkKTtcbiAgICAgIGlmICghZGVmaW5pdGlvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYENhbm5vdCByZXN1bWU6IHN1YmZsb3cgJyR7c3ViZmxvd0lkfScgaXMgbm90IHJlZ2lzdGVyZWQgaW4gdGhlIGZsb3djaGFydC4gYCArXG4gICAgICAgICAgICAnVGhlIGNoYXJ0IG1heSBoYXZlIGNoYW5nZWQgc2luY2UgdGhlIGNoZWNrcG9pbnQgd2FzIGNyZWF0ZWQuJyxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIGdyYXBocy5wdXNoKGRlZmluaXRpb24ucm9vdCk7XG4gICAgfVxuICAgIGNvbnN0IGxlYWZMZXZlbCA9IHBhdGgubGVuZ3RoO1xuICAgIC8vIFRoZSBwYXVzZWQgc3RhZ2UncyBSRUFMIG5vZGUg4oCUIHdob3NlIGRpc3BhdGNoZXIgdGhlIHN0YW5kLWluJ3NcbiAgICAvLyBjb250aW51YXRpb24gY29tZXMgZnJvbS4gKFRoZSBleGVjdXRvciBhbHJlYWR5IGZvdW5kIGl0OyBhIGRpcmVjdFxuICAgIC8vIGNhbGxlcidzIHN0YW5kLWluIHRoYXQgaXMgbm90IGluIHRoZSBsZWFmIGdyYXBoIHNpbXBseSBoYXMgbm9uZS4pXG4gICAgY29uc3QgcGF1c2VkID0gY2hhcnQuc3RhZ2UoZ3JhcGhzW2xlYWZMZXZlbF0sIHN0YW5kSW4uaWQpO1xuXG4gICAgLy8gMi4gUXVldWUgZXZlcnkgd2FpdGluZyBzaWJsaW5nIHBhdXNlIGF0IHRoZSBsZXZlbCBvZiBpdHMgZmFuLW91dC5cbiAgICBjb25zdCBxdWV1ZXMgPSBxdWV1ZVNpYmxpbmdQYXVzZXMoYXJncy5wZW5kaW5nUGF1c2VzLCB7IGNoYXJ0LCBzdWJmbG93cywgcm9vdCwgcGF0aCwgZ3JhcGhzLCBtb3VudHMsIHBhdXNlZCB9KTtcblxuICAgIC8vIDMuIFRoZSBvbmUtc2hvdCBlbnRyeSBvZiBldmVyeSBsZXZlbDogdGhlIGNoaWxkLCB0aGVuIGl0cyBkaXNwYXRjaGVyJ3NcbiAgICAvLyAgICBjb250aW51YXRpb24g4oCUIHVwIHRvIHRoZSBmYW4tb3V0IHdoZW4gc2libGluZ3Mgd2FpdCB0aGVyZS5cbiAgICBjb25zdCBjaGlsZEF0ID0gKGxldmVsOiBudW1iZXIpID0+IChsZXZlbCA8IGxlYWZMZXZlbCA/IG1vdW50c1tsZXZlbF0gOiBwYXVzZWQpO1xuICAgIGNvbnN0IGVudHJ5QXQgPSAobGV2ZWw6IG51bWJlcik6IFN0YWdlTm9kZTxUT3V0LCBUU2NvcGU+ID0+IHtcbiAgICAgIGNvbnN0IGNoaWxkID0gY2hpbGRBdChsZXZlbCk7XG4gICAgICBjb25zdCByZXBsYWNlbWVudCA9IGxldmVsIDwgbGVhZkxldmVsID8gbW91bnRzW2xldmVsXSA6IHN0YW5kSW47XG4gICAgICBpZiAoIWNoaWxkKSByZXR1cm4gcmVwbGFjZW1lbnQ7XG4gICAgICByZXR1cm4gY2hhcnQuZW50cnkoZ3JhcGhzW2xldmVsXSwgY2hpbGQsIHJlcGxhY2VtZW50LCBxdWV1ZXNbbGV2ZWxdPy5mYW5PdXQpO1xuICAgIH07XG4gICAgLy8gNC4gVGhlIGhvcHMuIEEgc3ViZmxvdyB3aXRoIG5vIGNhcHR1cmUgaXMgZW50ZXJlZCBhdCBpdHMgUk9PVCB3aXRoIGl0c1xuICAgIC8vICAgIGlucHV0TWFwcGVyIChpdHMgZWFybGllciBzdGFnZXMgcmVjb21wdXRlIHdoYXQgdGhlIGNhcHR1cmUgaGVsZCkg4oCUXG4gICAgLy8gICAgZXhjZXB0IHRoZSBsZWFmLCB3aG9zZSBlbnRyeSBpcyBhbHdheXMgdGhlIHN0YW5kLWluOiByZS1ydW5uaW5nIGl0XG4gICAgLy8gICAgZnJvbSBpdHMgcm9vdCB3b3VsZCBhc2sgYWdhaW4gYW5kIGxvc2UgdGhlIGFuc3dlci5cbiAgICBjb25zdCBob3BzOiBSZXN1bWVIb3A8VE91dCwgVFNjb3BlPltdID0gW107XG4gICAgbGV0IGV2ZXJ5TGV2ZWxBdEl0c0VudHJ5ID0gdHJ1ZTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBhdGgubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IHN1YmZsb3dJZCA9IHBhdGhbaV07XG4gICAgICBjb25zdCBzZWVkID0gb3duRW50cnkoY2FwdHVyZXMsIHN1YmZsb3dJZCk7XG4gICAgICBjb25zdCBpc0xlYWZIb3AgPSBpID09PSBwYXRoLmxlbmd0aCAtIDE7XG4gICAgICBpZiAoc2VlZCA9PT0gdW5kZWZpbmVkICYmICFpc0xlYWZIb3ApIHtcbiAgICAgICAgZXZlcnlMZXZlbEF0SXRzRW50cnkgPSBmYWxzZTtcbiAgICAgICAgaG9wcy5wdXNoKHsgc3ViZmxvd0lkIH0pO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHdhaXRpbmcgPSBxdWV1ZXNbaSArIDFdPy5wYXVzZXM7XG4gICAgICBob3BzLnB1c2goe1xuICAgICAgICBzdWJmbG93SWQsXG4gICAgICAgIC4uLihzZWVkICE9PSB1bmRlZmluZWQgJiYgeyBzZWVkIH0pLFxuICAgICAgICBlbnRyeTogZW50cnlBdChpICsgMSksXG4gICAgICAgIC4uLih3YWl0aW5nICYmIHsgcGVuZGluZ1BhdXNlczogd2FpdGluZyB9KSxcbiAgICAgIH0pO1xuICAgIH1cbiAgICAvLyBFdmVyeSBsZXZlbCBlbnRlcmVkIGF0IGl0cyBlbnRyeTogb25lIGV4ZWN1dGlvbiAodGhlIG1vdW50KSBwZXIgbGV2ZWxcbiAgICAvLyBydW5zIGJlZm9yZSB0aGUgc3RhbmQtaW4uXG4gICAgcmV0dXJuIG5ldyBSZXN1bWVFbnRyeShlbnRyeUF0KDApLCBob3BzLCBxdWV1ZXNbMF0/LnBhdXNlcywgZXZlcnlMZXZlbEF0SXRzRW50cnkgPyBwYXRoLmxlbmd0aCA6IHVuZGVmaW5lZCk7XG4gIH1cblxuICAvKipcbiAgICogQSBzZWVkLW9ubHkgZW50cnk6IGVhY2ggY2FwdHVyZSBzZWVkcyB0aGUgRklSU1QgZW50cnkgaW50byBpdHMgc3ViZmxvdyxcbiAgICogd2hpY2ggdGhlbiBzdGFydHMgYXQgaXRzIG93biByb290LiBXaGF0IHRoZSBkZXByZWNhdGVkXG4gICAqIGBzdWJmbG93U3RhdGVzRm9yUmVzdW1lYCBvcHRpb24gKFRyYXZlcnNlck9wdGlvbnMgLyBIYW5kbGVyRGVwcykgbWVhbnNcbiAgICogc2luY2UgOS4yOC4wIOKAlCB0aGUgc2FtZSBvbmUtc2hvdCBsYXcsIHdpdGhvdXQgYSBzdGFuZC1pbiBvciBhIHBhdGguXG4gICAqL1xuICBzdGF0aWMgZnJvbUNhcHR1cmVzPFRPdXQsIFRTY29wZT4oY2FwdHVyZXM6IFJlY29yZDxzdHJpbmcsIFJlY29yZDxzdHJpbmcsIHVua25vd24+Pik6IFJlc3VtZUVudHJ5PFRPdXQsIFRTY29wZT4ge1xuICAgIHJldHVybiBuZXcgUmVzdW1lRW50cnk8VE91dCwgVFNjb3BlPihcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIE9iamVjdC5lbnRyaWVzKGNhcHR1cmVzKS5tYXAoKFtzdWJmbG93SWQsIHNlZWRdKSA9PiAoeyBzdWJmbG93SWQsIHNlZWQgfSkpLFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIHJlLWVudHJ5IGludG8gYHN1YmZsb3dJZGAsIHRha2VuIOKAlCBvciBgdW5kZWZpbmVkYCB3aGVuIHRoaXMgZW50cnkgaXNcbiAgICogYW4gb3JkaW5hcnkgb25lICh0aGUgc3ViZmxvdyBpcyBvZmYgdGhlIHBhdXNlIHBhdGgsIG9yIGl0cyBob3Agd2FzIGFscmVhZHlcbiAgICogdGFrZW4pLiBPTkUtU0hPVDogYSBob3AgaXMgcmV0dXJuZWQgYXQgbW9zdCBvbmNlLCBzbyBhIHNlY29uZCBlbnRyeSBpbnRvXG4gICAqIHRoZSBzYW1lIHN1YmZsb3cgKGEgbG9vcCBwYXNzaW5nIGl0cyBtb3VudCBhZ2FpbikgcnVucyB0aGUgcmVhbCBzdWJmbG93XG4gICAqIGZyb20gaXRzIHJlYWwgcm9vdCB3aXRoIGl0cyBpbnB1dE1hcHBlci5cbiAgICovXG4gIGVudGVyU3ViZmxvdyhzdWJmbG93SWQ6IHN0cmluZyk6IFJlc3VtZUhvcDxUT3V0LCBUU2NvcGU+IHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBob3AgPSB0aGlzLnBlbmRpbmcuZ2V0KHN1YmZsb3dJZCk7XG4gICAgaWYgKGhvcCAhPT0gdW5kZWZpbmVkKSB0aGlzLnBlbmRpbmcuZGVsZXRlKHN1YmZsb3dJZCk7XG4gICAgcmV0dXJuIGhvcDtcbiAgfVxuXG4gIC8qKiBgdHJ1ZWAgb25jZSBldmVyeSBob3AgaGFzIGJlZW4gdGFrZW4g4oCUIHRoZSByZXN0IG9mIHRoZSBydW4gaXMgb3JkaW5hcnkuICovXG4gIGdldCBzcGVudCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5wZW5kaW5nLnNpemUgPT09IDA7XG4gIH1cbn1cblxuLy8g4pSA4pSAIFJhaXNpbmcgYSB3YWl0aW5nIHNpYmxpbmcncyBwYXVzZSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuLyoqXG4gKiBRdWV1ZSBgcXVldWVgIGJlaGluZCBhIHBhdXNlIHBhc3NpbmcgdGhyb3VnaCBpdHMgbGV2ZWw6IGEgcGF1c2UgcmFpc2VkXG4gKiB3aGlsZSBzaWJsaW5ncyBzdGlsbCB3YWl0IG11c3QgY2FycnkgdGhlbSB0byBpdHMgY2hlY2twb2ludC4gRWFjaCBwYXRoIGlzXG4gKiBjdXQgdG8gdGhhdCBsZXZlbCDigJQgdGhlIGJ1YmJsZS11cCBwcmVwZW5kcyB0aGUgbGV2ZWxzIGFib3ZlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcXVldWVCZWhpbmQoc2lnbmFsOiBQYXVzZVNpZ25hbCwgcXVldWU6IHJlYWRvbmx5IFF1ZXVlZFBhdXNlW10pOiB2b2lkIHtcbiAgZm9yIChjb25zdCB7IHBhdXNlLCBsZXZlbCB9IG9mIHF1ZXVlKSB7XG4gICAgc2lnbmFsLmFkZFBlbmRpbmdQYXVzZSh7IC4uLnBhdXNlLCBzdWJmbG93UGF0aDogcGF1c2Uuc3ViZmxvd1BhdGguc2xpY2UobGV2ZWwpIH0pO1xuICB9XG59XG5cbi8qKlxuICogVGhlIGZpcnN0IHdhaXRpbmcgc2libGluZydzIHBhdXNlLCByYWlzZWQgYWdhaW4gYXQgaXRzIGZhbi1vdXQncyBsZXZlbCDigJRcbiAqIGV4YWN0bHkgYXMgaXQgYnViYmxlZCB1cCB0byB0aGF0IGxldmVsIHRoZSBmaXJzdCB0aW1lIChpdHMgc3RhZ2UsIGl0c1xuICogcXVlc3Rpb24sIGl0cyBvd24gc3ViZmxvdyBjYXB0dXJlcyksIG5vdGhpbmcgcmUtcnVuOyB0aGUgcmVzdCBvZiB0aGUgcXVldWVcbiAqIHdhaXRzIGJlaGluZCBpdC4gVGhlIHN1YmZsb3dzIEFCT1ZFIHRoZSBmYW4tb3V0IGNhcHR1cmUgdGhlbXNlbHZlcyBhZnJlc2hcbiAqIGFzIGl0IGJ1YmJsZXMgdXAsIHNvIHRoZXkgY2Fycnkgd2hhdCB0aGUgcmVzdW1lZCBjaGlsZCB3cm90ZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJhaXNlUXVldWVkUGF1c2UocXVldWU6IHJlYWRvbmx5IFF1ZXVlZFBhdXNlW10pOiBQYXVzZVNpZ25hbCB7XG4gIGNvbnN0IFtmaXJzdCwgLi4ucmVzdF0gPSBxdWV1ZTtcbiAgY29uc3QgeyBwYXVzZSwgbGV2ZWwgfSA9IGZpcnN0O1xuICBjb25zdCBzaWduYWwgPSBuZXcgUGF1c2VTaWduYWwocGF1c2UucGF1c2VEYXRhLCBwYXVzZS5wYXVzZWRTdGFnZUlkLCBwYXVzZS5wYXVzZWRCeSk7XG4gIGNvbnN0IGJlbG93ID0gcGF1c2Uuc3ViZmxvd1BhdGguc2xpY2UobGV2ZWwpO1xuICBmb3IgKGxldCBpID0gYmVsb3cubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBjb25zdCBzdGF0ZSA9IG93bkVudHJ5KHBhdXNlLnN1YmZsb3dTdGF0ZXMsIGJlbG93W2ldKTtcbiAgICBpZiAoc3RhdGUgIT09IHVuZGVmaW5lZCkgc2lnbmFsLmNhcHR1cmVTdWJmbG93U2NvcGUoYmVsb3dbaV0sIHN0YXRlKTtcbiAgICBzaWduYWwucHJlcGVuZFN1YmZsb3coYmVsb3dbaV0pO1xuICB9XG4gIHF1ZXVlQmVoaW5kKHNpZ25hbCwgcmVzdCk7XG4gIHJldHVybiBzaWduYWw7XG59XG5cbi8vIOKUgOKUgCBSZWFkaW5nIHRoZSBjaGFydCDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuLyoqXG4gKiBUaGUgbm9kZSB0aGF0IG1vdW50cyBgc3ViZmxvd0lkYCwgZm91bmQgYnkgREZTIGZyb20gYHN0YXJ0YCBvdmVyIGBuZXh0YCBhbmRcbiAqIGBjaGlsZHJlbmAgKGxvb3AtcmVmIHN0dWJzIHNraXBwZWQg4oCUIHRoZXkgc2hhcmUgdGhlaXIgdGFyZ2V0J3MgaWQgYW5kIGNhcnJ5XG4gKiBub3RoaW5nKS4gQ3ljbGUtc2FmZSAodmlzaXRlZCBieSBpZGVudGl0eSwgc28gYW4gYWJzZW50IGlkIHRlcm1pbmF0ZXMgdG9vKTtcbiAqIGZpcnN0IG1hdGNoIGluIERGUyBwcmUtb3JkZXIgKGNoaWxkcmVuIGJlZm9yZSBgbmV4dGAsIGxpa2UgdGhlIGJ1aWxkZXIpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZmluZE1vdW50PFRPdXQsIFRTY29wZT4oXG4gIHN0YXJ0OiBTdGFnZU5vZGU8VE91dCwgVFNjb3BlPixcbiAgc3ViZmxvd0lkOiBzdHJpbmcsXG4pOiBTdGFnZU5vZGU8VE91dCwgVFNjb3BlPiB8IHVuZGVmaW5lZCB7XG4gIGZvciAoY29uc3Qgbm9kZSBvZiBkaXNwYXRjaGVySW5kZXgoc3RhcnQpLmtleXMoKSkge1xuICAgIGlmIChub2RlLnN1YmZsb3dJZCA9PT0gc3ViZmxvd0lkKSByZXR1cm4gbm9kZTtcbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIEV2ZXJ5IHJlYWwgbm9kZSBvZiBvbmUgbGV2ZWwncyBncmFwaCwgaW4gREZTIHByZS1vcmRlciwgbWFwcGVkIHRvIHRoZVxuICogRElTUEFUQ0hFUiB3aG9zZSBjaGlsZC1jaGFpbiBob2xkcyBpdCDigJQgdGhlIG5vZGUgd2hvc2UgYGNoaWxkcmVuYCBpdFxuICogZGVzY2VuZHMgZnJvbSAoYSBkZWNpZGVyLCBhIHNlbGVjdG9yLCBhIGZvcmspIOKAlCBvciBgdW5kZWZpbmVkYCBmb3IgYSBub2RlXG4gKiBvbiB0aGUgbGV2ZWwncyBvd24gc3BpbmUuIExvb3Agc3R1YnMgYXJlIHNraXBwZWQ7IHZpc2l0ZWQgYnkgaWRlbnRpdHksIHNvXG4gKiB0d28gbW91bnRzIHNoYXJpbmcgYW4gaWQgYXJlIGJvdGggaW5kZXhlZCBhbmQgYSBjeWNsZSB0ZXJtaW5hdGVzLlxuICovXG5mdW5jdGlvbiBkaXNwYXRjaGVySW5kZXg8VE91dCwgVFNjb3BlPihcbiAgcm9vdDogU3RhZ2VOb2RlPFRPdXQsIFRTY29wZT4sXG4pOiBNYXA8U3RhZ2VOb2RlPFRPdXQsIFRTY29wZT4sIFN0YWdlTm9kZTxUT3V0LCBUU2NvcGU+IHwgdW5kZWZpbmVkPiB7XG4gIGNvbnN0IGluZGV4ID0gbmV3IE1hcDxTdGFnZU5vZGU8VE91dCwgVFNjb3BlPiwgU3RhZ2VOb2RlPFRPdXQsIFRTY29wZT4gfCB1bmRlZmluZWQ+KCk7XG4gIGNvbnN0IHN0YWNrOiBBcnJheTxbU3RhZ2VOb2RlPFRPdXQsIFRTY29wZT4sIFN0YWdlTm9kZTxUT3V0LCBUU2NvcGU+IHwgdW5kZWZpbmVkXT4gPSBbW3Jvb3QsIHVuZGVmaW5lZF1dO1xuICBmb3IgKGxldCB0b3AgPSBzdGFjay5wb3AoKTsgdG9wICE9PSB1bmRlZmluZWQ7IHRvcCA9IHN0YWNrLnBvcCgpKSB7XG4gICAgY29uc3QgW25vZGUsIGRpc3BhdGNoZXJdID0gdG9wO1xuICAgIGlmIChub2RlLmlzTG9vcFJlZiB8fCBpbmRleC5oYXMobm9kZSkpIGNvbnRpbnVlO1xuICAgIGluZGV4LnNldChub2RlLCBkaXNwYXRjaGVyKTtcbiAgICAvLyBMSUZPOiBwdXNoIGBuZXh0YCBmaXJzdCBhbmQgY2hpbGRyZW4gcmV2ZXJzZWQsIHNvIGNoaWxkcmVuIGFyZSB2aXNpdGVkXG4gICAgLy8gYmVmb3JlIGBuZXh0YCBhbmQgdGhlIGZpcnN0IGNoaWxkIGZpcnN0IOKAlCBwcmUtb3JkZXIsIGxpa2UgdGhlIGJ1aWxkZXIuXG4gICAgaWYgKG5vZGUubmV4dCkgc3RhY2sucHVzaChbbm9kZS5uZXh0LCBkaXNwYXRjaGVyXSk7XG4gICAgaWYgKG5vZGUuY2hpbGRyZW4pIHtcbiAgICAgIGZvciAobGV0IGkgPSBub2RlLmNoaWxkcmVuLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBzdGFjay5wdXNoKFtub2RlLmNoaWxkcmVuW2ldLCBub2RlXSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBpbmRleDtcbn1cblxuLyoqIE9uZSBwbGFuJ3MgdmlldyBvZiB0aGUgY2hhcnQ6IGVhY2ggbGV2ZWwncyBpbmRleCBidWlsdCBvbmNlLiAqL1xuY2xhc3MgQ2hhcnRJbmRleDxUT3V0LCBUU2NvcGU+IHtcbiAgcHJpdmF0ZSByZWFkb25seSBpbmRleGVzID0gbmV3IE1hcDxcbiAgICBTdGFnZU5vZGU8VE91dCwgVFNjb3BlPixcbiAgICBNYXA8U3RhZ2VOb2RlPFRPdXQsIFRTY29wZT4sIFN0YWdlTm9kZTxUT3V0LCBUU2NvcGU+IHwgdW5kZWZpbmVkPlxuICA+KCk7XG5cbiAgcHJpdmF0ZSBvZihyb290OiBTdGFnZU5vZGU8VE91dCwgVFNjb3BlPikge1xuICAgIGxldCBpbmRleCA9IHRoaXMuaW5kZXhlcy5nZXQocm9vdCk7XG4gICAgaWYgKCFpbmRleCkge1xuICAgICAgaW5kZXggPSBkaXNwYXRjaGVySW5kZXgocm9vdCk7XG4gICAgICB0aGlzLmluZGV4ZXMuc2V0KHJvb3QsIGluZGV4KTtcbiAgICB9XG4gICAgcmV0dXJuIGluZGV4O1xuICB9XG5cbiAgLyoqIEV2ZXJ5IG1vdW50IG9mIGBzdWJmbG93SWRgIGluIGByb290YCdzIGdyYXBoLCBpbiBERlMgcHJlLW9yZGVyLiAqL1xuICBtb3VudHNPZihyb290OiBTdGFnZU5vZGU8VE91dCwgVFNjb3BlPiwgc3ViZmxvd0lkOiBzdHJpbmcpOiBTdGFnZU5vZGU8VE91dCwgVFNjb3BlPltdIHtcbiAgICByZXR1cm4gWy4uLnRoaXMub2Yocm9vdCkua2V5cygpXS5maWx0ZXIoKG5vZGUpID0+IG5vZGUuc3ViZmxvd0lkID09PSBzdWJmbG93SWQpO1xuICB9XG5cbiAgLyoqIFRoZSBvbmUgbW91bnQgb2YgYHN1YmZsb3dJZGAgaW4gYHJvb3RgJ3MgZ3JhcGgg4oCUIHJlZnVzZWQgd2hlbiBhYnNlbnQgb3IgYW1iaWd1b3VzLiAqL1xuICBvbmx5TW91bnQocm9vdDogU3RhZ2VOb2RlPFRPdXQsIFRTY29wZT4sIHN1YmZsb3dJZDogc3RyaW5nLCBncmFwaE5hbWU6IHN0cmluZyk6IFN0YWdlTm9kZTxUT3V0LCBUU2NvcGU+IHtcbiAgICBjb25zdCBmb3VuZCA9IHRoaXMubW91bnRzT2Yocm9vdCwgc3ViZmxvd0lkKTtcbiAgICBpZiAoZm91bmQubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBDYW5ub3QgcmVzdW1lOiB0aGUgbW91bnQgb2Ygc3ViZmxvdyAnJHtzdWJmbG93SWR9JyBpcyBub3QgcmVhY2hhYmxlIGZyb20gJHtncmFwaE5hbWV9LiBgICtcbiAgICAgICAgICBcIlRoZSBjaGVja3BvaW50J3Mgc3ViZmxvd1BhdGggZG9lcyBub3QgbWF0Y2ggdGhpcyBjaGFydCDigJQgaXQgbWF5IGhhdmUgY2hhbmdlZCBzaW5jZSB0aGUgY2hlY2twb2ludCB3YXMgY3JlYXRlZC5cIixcbiAgICAgICk7XG4gICAgfVxuICAgIGlmIChmb3VuZC5sZW5ndGggPiAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBDYW5ub3QgcmVzdW1lOiBzdWJmbG93ICcke3N1YmZsb3dJZH0nIGlzIG1vdW50ZWQgbW9yZSB0aGFuIG9uY2UgaW4gJHtncmFwaE5hbWV9IGAgK1xuICAgICAgICAgIGAoJHtmb3VuZC5tYXAoKG5vZGUpID0+IGAnJHtub2RlLm5hbWV9J2ApLmpvaW4oJywgJyl9KSwgYW5kIGEgY2hlY2twb2ludCdzIHN1YmZsb3dQYXRoIGNhbm5vdCBzYXkgd2hpY2ggYCArXG4gICAgICAgICAgJ21vdW50IHBhdXNlZC4gR2l2ZSBlYWNoIG1vdW50IGl0cyBvd24gc3ViZmxvdyBpZCB0byBtYWtlIGEgcGF1c2UgaW5zaWRlIGl0IHJlc3VtYWJsZS4nLFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIGZvdW5kWzBdO1xuICB9XG5cbiAgLyoqIFRoZSByZWFsIHN0YWdlIGBpZGAgaW4gYHJvb3RgJ3MgZ3JhcGggKGZpcnN0IGluIERGUyBwcmUtb3JkZXIpLCBpZiBhbnkuICovXG4gIHN0YWdlKHJvb3Q6IFN0YWdlTm9kZTxUT3V0LCBUU2NvcGU+LCBpZDogc3RyaW5nKTogU3RhZ2VOb2RlPFRPdXQsIFRTY29wZT4gfCB1bmRlZmluZWQge1xuICAgIGZvciAoY29uc3Qgbm9kZSBvZiB0aGlzLm9mKHJvb3QpLmtleXMoKSkgaWYgKG5vZGUuaWQgPT09IGlkKSByZXR1cm4gbm9kZTtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqIFRoZSBkaXNwYXRjaGVyIHdob3NlIGNoaWxkLWNoYWluIGhvbGRzIGBub2RlYCBpbiBgcm9vdGAncyBncmFwaCAoYHVuZGVmaW5lZGAgb24gdGhlIHNwaW5lKS4gKi9cbiAgZGlzcGF0Y2hlck9mKHJvb3Q6IFN0YWdlTm9kZTxUT3V0LCBUU2NvcGU+LCBub2RlOiBTdGFnZU5vZGU8VE91dCwgVFNjb3BlPik6IFN0YWdlTm9kZTxUT3V0LCBUU2NvcGU+IHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5vZihyb290KS5nZXQobm9kZSk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIG9uZS1zaG90IGVudHJ5IGZvciBgY2hpbGRgIChhIG1vdW50IG9uIHRoZSBwYXRoLCBvciB0aGUgcGF1c2VkIHN0YWdlKVxuICAgKiBpbiBgcm9vdGAncyBncmFwaDogYHJlcGxhY2VtZW50YCAodGhlIG5vZGUgdGhhdCBydW5zIOKAlCB0aGUgbW91bnQgaXRzZWxmLFxuICAgKiBvciB0aGUgc3RhbmQtaW4pIHdpdGggd2hhdCByYW4gYWZ0ZXIgYGNoaWxkYCdzIGNoYWluIG9uIHRoZSBvcmlnaW5hbCBydW5cbiAgICogYXR0YWNoZWQgd2hlcmUgdGhhdCBjaGFpbiBlbmRzIOKAlCBgeyAuLi5jaGlsZCwgbmV4dDogZGlzcGF0Y2hlci5uZXh0IH1gIGZvclxuICAgKiBhIGNoYXJ0IHRoZSBidWlsZGVyIG1hZGU6XG4gICAqXG4gICAqICAg4oCiIG9uIHRoZSBsZXZlbCdzIHNwaW5lOiBub3RoaW5nIHRvIGF0dGFjaCDigJQgdGhlIHNwaW5lIGdvZXMgb24gYnkgaXRzZWxmO1xuICAgKiAgIOKAoiBhIERFQ0lERVIncyBvciBTRUxFQ1RPUidzIGJyYW5jaDogdGhlIGRpc3BhdGNoZXIncyBgbmV4dGA7XG4gICAqICAg4oCiIGEgRk9SSyBjaGlsZDogdGhlIGZvcmsncyBgbmV4dGAg4oCUIGl0cyBqb2luLlxuICAgKlxuICAgKiBQYXN0IGEgZGlzcGF0Y2hlciB3aXRoIG5vIGBuZXh0YCwgdGhlIHdhbGsgZ29lcyBvbiBPVVRXQVJEIHRvIHRoZSBvbmVcbiAgICogZW5jbG9zaW5nIGl0LiBJdCBzdG9wcyBhdCBgc3RvcEF0YCDigJQgdGhlIGZhbi1vdXQgd2hlcmUgc2libGluZ3Mgc3RpbGxcbiAgICogd2FpdCwgd2hvc2Ugam9pbiBtdXN0IG5vdCBydW4geWV0LiBOb3RoaW5nIHRvIGF0dGFjaDogYHJlcGxhY2VtZW50YFxuICAgKiBpdHNlbGYuXG4gICAqL1xuICBlbnRyeShcbiAgICByb290OiBTdGFnZU5vZGU8VE91dCwgVFNjb3BlPixcbiAgICBjaGlsZDogU3RhZ2VOb2RlPFRPdXQsIFRTY29wZT4sXG4gICAgcmVwbGFjZW1lbnQ6IFN0YWdlTm9kZTxUT3V0LCBUU2NvcGU+LFxuICAgIHN0b3BBdDogU3RhZ2VOb2RlPFRPdXQsIFRTY29wZT4gfCB1bmRlZmluZWQsXG4gICk6IFN0YWdlTm9kZTxUT3V0LCBUU2NvcGU+IHtcbiAgICByZXR1cm4gYXBwZW5kQXRDaGFpbkVuZChyZXBsYWNlbWVudCwgdGhpcy5hZnRlcihyb290LCBjaGlsZCwgc3RvcEF0KSk7XG4gIH1cblxuICAvKipcbiAgICogV2hhdCBydW5zIG9uY2UgYG5vZGVgJ3MgY2hhaW4gZW5kczogaXRzIGRpc3BhdGNoZXIncyBgbmV4dGAgY2hhaW4sIHRoZW4g4oCUXG4gICAqIHdoZXJlIFRIQVQgZW5kcyDigJQgdGhlIGNvbnRpbnVhdGlvbiBvZiB0aGUgZGlzcGF0Y2hlciBlbmNsb3NpbmcgaXQsIG91dHdhcmQsXG4gICAqIHVwIHRvIGBzdG9wQXRgIChleGNsdXNpdmUpLiBgdW5kZWZpbmVkYCBvbiB0aGUgc3BpbmUuXG4gICAqL1xuICBwcml2YXRlIGFmdGVyKFxuICAgIHJvb3Q6IFN0YWdlTm9kZTxUT3V0LCBUU2NvcGU+LFxuICAgIG5vZGU6IFN0YWdlTm9kZTxUT3V0LCBUU2NvcGU+LFxuICAgIHN0b3BBdDogU3RhZ2VOb2RlPFRPdXQsIFRTY29wZT4gfCB1bmRlZmluZWQsXG4gICk6IFN0YWdlTm9kZTxUT3V0LCBUU2NvcGU+IHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBkaXNwYXRjaGVyID0gdGhpcy5kaXNwYXRjaGVyT2Yocm9vdCwgbm9kZSk7XG4gICAgaWYgKGRpc3BhdGNoZXIgPT09IHVuZGVmaW5lZCB8fCBkaXNwYXRjaGVyID09PSBzdG9wQXQpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgY29uc3Qgb3V0ZXIgPSB0aGlzLmFmdGVyKHJvb3QsIGRpc3BhdGNoZXIsIHN0b3BBdCk7XG4gICAgcmV0dXJuIGRpc3BhdGNoZXIubmV4dCA/IGFwcGVuZEF0Q2hhaW5FbmQoZGlzcGF0Y2hlci5uZXh0LCBvdXRlcikgOiBvdXRlcjtcbiAgfVxufVxuXG4vKipcbiAqIGBzdGFydGAncyBjaGFpbiB3aXRoIGBhZnRlcmAgYXR0YWNoZWQgd2hlcmUgaXQgZW5kcyDigJQgdGhlIGNoYWluJ3Mgbm9kZXNcbiAqIGNvcGllZCBvbiB0aGUgd2F5IChuZXZlciByZWdpc3RlcmVkIGFueXdoZXJlOiBpZHMgc3RpbGwgcmVzb2x2ZSB0byB0aGUgcmVhbFxuICogbm9kZXMpLiBBIGNoYWluIHRoYXQgZW5kcyBpbiBhIGxvb3Agc3R1YiAob3IgbG9vcHMgYmFjayBvbiBpdHNlbGYpIGlzXG4gKiByZXR1cm5lZCBhcyBpczogY29udHJvbCBsZWF2ZXMgaXQgdGhyb3VnaCB0aGUgbG9vcCwgbmV2ZXIgXCJhZnRlclwiIGl0LlxuICovXG5mdW5jdGlvbiBhcHBlbmRBdENoYWluRW5kPFRPdXQsIFRTY29wZT4oXG4gIHN0YXJ0OiBTdGFnZU5vZGU8VE91dCwgVFNjb3BlPixcbiAgYWZ0ZXI6IFN0YWdlTm9kZTxUT3V0LCBUU2NvcGU+IHwgdW5kZWZpbmVkLFxuKTogU3RhZ2VOb2RlPFRPdXQsIFRTY29wZT4ge1xuICBpZiAoYWZ0ZXIgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHN0YXJ0O1xuICBjb25zdCBjaGFpbjogU3RhZ2VOb2RlPFRPdXQsIFRTY29wZT5bXSA9IFtdO1xuICBjb25zdCBzZWVuID0gbmV3IFNldDxTdGFnZU5vZGU8VE91dCwgVFNjb3BlPj4oKTtcbiAgZm9yIChsZXQgbm9kZTogU3RhZ2VOb2RlPFRPdXQsIFRTY29wZT4gfCB1bmRlZmluZWQgPSBzdGFydDsgbm9kZSAhPT0gdW5kZWZpbmVkOyBub2RlID0gbm9kZS5uZXh0KSB7XG4gICAgaWYgKG5vZGUuaXNMb29wUmVmIHx8IHNlZW4uaGFzKG5vZGUpKSByZXR1cm4gc3RhcnQ7XG4gICAgc2Vlbi5hZGQobm9kZSk7XG4gICAgY2hhaW4ucHVzaChub2RlKTtcbiAgfVxuICBsZXQgbmV4dCA9IGFmdGVyO1xuICBmb3IgKGxldCBpID0gY2hhaW4ubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIG5leHQgPSB7IC4uLmNoYWluW2ldLCBuZXh0IH07XG4gIHJldHVybiBuZXh0O1xufVxuXG4vLyDilIDilIAgV2FpdGluZyBzaWJsaW5ncyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuLyoqIFRoZSBzaWJsaW5nIHBhdXNlcyB3YWl0aW5nIGF0IG9uZSBsZXZlbCwgYW5kIHRoZSBmYW4tb3V0IHRoZXkgd2FpdCBpbi4gKi9cbmludGVyZmFjZSBMZXZlbFF1ZXVlPFRPdXQsIFRTY29wZT4ge1xuICByZWFkb25seSBmYW5PdXQ6IFN0YWdlTm9kZTxUT3V0LCBUU2NvcGU+O1xuICByZWFkb25seSBwYXVzZXM6IFF1ZXVlZFBhdXNlW107XG59XG5cbi8qKlxuICogVmFsaWRhdGUgYGNoZWNrcG9pbnQucGVuZGluZ1BhdXNlc2AgKHVudHJ1c3RlZCBpbnB1dCkgYW5kIHF1ZXVlIGVhY2ggYXQgdGhlXG4gKiBsZXZlbCBvZiBpdHMgZmFuLW91dDogdGhlIGRlcHRoIHdoZXJlIGl0cyBwYXRoIHBhcnRzIGZyb20gdGhlIHBhdXNlZFxuICogc3RhZ2Uncy4gVGhlcmUsIHRoZSBwYXVzZWQgc3RhZ2UncyBjaGlsZCAoYSBtb3VudCBvbiB0aGUgcGF0aCwgb3IgdGhlIHN0YWdlXG4gKiBpdHNlbGYpIGFuZCB0aGUgc2libGluZydzIG11c3QgYm90aCBoYW5nIG9mZiBPTkUgcGFyYWxsZWwgZGlzcGF0Y2hlciDigJQgYVxuICogZm9yayBvciBhIHNlbGVjdG9yIOKAlCBvciB0aGUgcmVjb3JkIGlzIG5vdCBhIHNpYmxpbmcgYW5kIHRoZSByZXN1bWUgaXNcbiAqIHJlZnVzZWQgcmF0aGVyIHRoYW4gYXNrZWQgYSBxdWVzdGlvbiB0aGUgY2hhcnQgY291bGQgbm90IGhhdmUgcmFpc2VkLlxuICovXG5mdW5jdGlvbiBxdWV1ZVNpYmxpbmdQYXVzZXM8VE91dCwgVFNjb3BlPihcbiAgcGVuZGluZzogcmVhZG9ubHkgUGVuZGluZ1BhdXNlW10gfCB1bmRlZmluZWQsXG4gIGF0OiB7XG4gICAgY2hhcnQ6IENoYXJ0SW5kZXg8VE91dCwgVFNjb3BlPjtcbiAgICBzdWJmbG93czogUmVjb3JkPHN0cmluZywgeyByb290OiBTdGFnZU5vZGU8VE91dCwgVFNjb3BlPiB9PiB8IHVuZGVmaW5lZDtcbiAgICByb290OiBTdGFnZU5vZGU8VE91dCwgVFNjb3BlPjtcbiAgICBwYXRoOiByZWFkb25seSBzdHJpbmdbXTtcbiAgICBncmFwaHM6IHJlYWRvbmx5IFN0YWdlTm9kZTxUT3V0LCBUU2NvcGU+W107XG4gICAgbW91bnRzOiByZWFkb25seSBTdGFnZU5vZGU8VE91dCwgVFNjb3BlPltdO1xuICAgIHBhdXNlZDogU3RhZ2VOb2RlPFRPdXQsIFRTY29wZT4gfCB1bmRlZmluZWQ7XG4gIH0sXG4pOiBBcnJheTxMZXZlbFF1ZXVlPFRPdXQsIFRTY29wZT4gfCB1bmRlZmluZWQ+IHtcbiAgY29uc3QgcXVldWVzOiBBcnJheTxMZXZlbFF1ZXVlPFRPdXQsIFRTY29wZT4gfCB1bmRlZmluZWQ+ID0gW107XG4gIGlmIChwZW5kaW5nID09PSB1bmRlZmluZWQpIHJldHVybiBxdWV1ZXM7XG4gIGlmICghQXJyYXkuaXNBcnJheShwZW5kaW5nKSkgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGNoZWNrcG9pbnQ6IHBlbmRpbmdQYXVzZXMgbXVzdCBiZSBhbiBhcnJheS4nKTtcbiAgY29uc3QgeyBjaGFydCwgc3ViZmxvd3MsIHJvb3QsIHBhdGgsIGdyYXBocywgbW91bnRzLCBwYXVzZWQgfSA9IGF0O1xuICBjb25zdCBzZWVuID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgcGVuZGluZy5mb3JFYWNoKChyYXc6IHVua25vd24sIG4pID0+IHtcbiAgICBjb25zdCBwYXVzZSA9IHZhbGlkUGVuZGluZ1BhdXNlKHJhdywgbik7XG4gICAgLy8gT25lIHJlY29yZCBwZXIgcGF1c2VkIHNpYmxpbmc6IGEgcmVwZWF0IHdvdWxkIGFzayB0aGUgc2FtZSBxdWVzdGlvbiB0d2ljZS5cbiAgICBjb25zdCBrZXkgPSBKU09OLnN0cmluZ2lmeShbcGF1c2Uuc3ViZmxvd1BhdGgsIHBhdXNlLnBhdXNlZFN0YWdlSWRdKTtcbiAgICBpZiAoc2Vlbi5oYXMoa2V5KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgQ2Fubm90IHJlc3VtZTogY2hlY2twb2ludC5wZW5kaW5nUGF1c2VzWyR7bn1dICgnJHtwYXVzZS5wYXVzZWRTdGFnZUlkfScpIHJlcGVhdHMgYW4gZWFybGllciBlbnRyeS5gLFxuICAgICAgKTtcbiAgICB9XG4gICAgc2Vlbi5hZGQoa2V5KTtcbiAgICBsZXQgbGV2ZWwgPSAwO1xuICAgIHdoaWxlIChsZXZlbCA8IHBhdGgubGVuZ3RoICYmIGxldmVsIDwgcGF1c2Uuc3ViZmxvd1BhdGgubGVuZ3RoICYmIHBhdGhbbGV2ZWxdID09PSBwYXVzZS5zdWJmbG93UGF0aFtsZXZlbF0pIGxldmVsKys7XG4gICAgY29uc3QgZ3JhcGggPSBncmFwaHNbbGV2ZWxdO1xuICAgIGNvbnN0IG91cnMgPSBsZXZlbCA8IHBhdGgubGVuZ3RoID8gbW91bnRzW2xldmVsXSA6IHBhdXNlZDtcbiAgICBjb25zdCB0aGVpck1vdW50cyA9IGxldmVsIDwgcGF1c2Uuc3ViZmxvd1BhdGgubGVuZ3RoID8gY2hhcnQubW91bnRzT2YoZ3JhcGgsIHBhdXNlLnN1YmZsb3dQYXRoW2xldmVsXSkgOiBbXTtcbiAgICBjb25zdCB0aGVpcnMgPVxuICAgICAgbGV2ZWwgPCBwYXVzZS5zdWJmbG93UGF0aC5sZW5ndGhcbiAgICAgICAgPyB0aGVpck1vdW50cy5sZW5ndGggPT09IDFcbiAgICAgICAgICA/IHRoZWlyTW91bnRzWzBdXG4gICAgICAgICAgOiB1bmRlZmluZWRcbiAgICAgICAgOiBjaGFydC5zdGFnZShncmFwaCwgcGF1c2UucGF1c2VkU3RhZ2VJZCk7XG4gICAgY29uc3QgZmFuT3V0ID0gb3VycyA/IGNoYXJ0LmRpc3BhdGNoZXJPZihncmFwaCwgb3VycykgOiB1bmRlZmluZWQ7XG4gICAgY29uc3QgaXNTaWJsaW5nID1cbiAgICAgIG91cnMgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgdGhlaXJzICE9PSB1bmRlZmluZWQgJiZcbiAgICAgIG91cnMgIT09IHRoZWlycyAmJlxuICAgICAgZmFuT3V0ICE9PSB1bmRlZmluZWQgJiZcbiAgICAgIGNoYXJ0LmRpc3BhdGNoZXJPZihncmFwaCwgdGhlaXJzKSA9PT0gZmFuT3V0ICYmXG4gICAgICAhZmFuT3V0LmRlY2lkZXJGbiAmJlxuICAgICAgKHF1ZXVlc1tsZXZlbF0gPT09IHVuZGVmaW5lZCB8fCBxdWV1ZXNbbGV2ZWxdIS5mYW5PdXQgPT09IGZhbk91dCk7XG4gICAgaWYgKCFpc1NpYmxpbmcgfHwgIXdhbGtzVG9JdHNTdGFnZShjaGFydCwgc3ViZmxvd3MsIGdyYXBoLCBwYXVzZSwgbGV2ZWwpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBDYW5ub3QgcmVzdW1lOiBjaGVja3BvaW50LnBlbmRpbmdQYXVzZXNbJHtufV0gKCcke3BhdXNlLnBhdXNlZFN0YWdlSWR9JykgaXMgbm90IGEgcGFyYWxsZWwgc2libGluZyBvZiBgICtcbiAgICAgICAgICBgdGhlIHBhdXNlZCBzdGFnZSAnJHtwYXVzZWQ/LmlkID8/ICc/J30nIGluIHRoaXMgY2hhcnQg4oCUIG5vIGZvcmsgb3Igc2VsZWN0b3IgcnVucyB0aGVtIGJvdGgsIG9yIGl0cyBgICtcbiAgICAgICAgICAncGF0aCBkb2VzIG5vdCBsZWFkIHRvIHRoYXQgc3RhZ2UuIFRoZSBjaGFydCBtYXkgaGF2ZSBjaGFuZ2VkIHNpbmNlIHRoZSBjaGVja3BvaW50IHdhcyBjcmVhdGVkLicsXG4gICAgICApO1xuICAgIH1cbiAgICBjb25zdCBsZWFmUm9vdCA9XG4gICAgICBwYXVzZS5zdWJmbG93UGF0aC5sZW5ndGggPT09IDAgPyByb290IDogb3duRW50cnkoc3ViZmxvd3MsIHBhdXNlLnN1YmZsb3dQYXRoW3BhdXNlLnN1YmZsb3dQYXRoLmxlbmd0aCAtIDFdKT8ucm9vdDtcbiAgICBjb25zdCBzdGFnZU5hbWUgPSAobGVhZlJvb3QgJiYgY2hhcnQuc3RhZ2UobGVhZlJvb3QsIHBhdXNlLnBhdXNlZFN0YWdlSWQpPy5uYW1lKSA/PyBwYXVzZS5wYXVzZWRTdGFnZUlkO1xuICAgIGNvbnN0IHF1ZXVlID0gKHF1ZXVlc1tsZXZlbF0gPz89IHsgZmFuT3V0OiBmYW5PdXQhLCBwYXVzZXM6IFtdIH0pO1xuICAgIHF1ZXVlLnBhdXNlcy5wdXNoKHsgcGF1c2UsIGxldmVsLCBzdGFnZU5hbWUgfSk7XG4gIH0pO1xuICByZXR1cm4gcXVldWVzO1xufVxuXG4vKipcbiAqIFdoZXRoZXIgYSB3YWl0aW5nIHNpYmxpbmcncyBXSE9MRSBwYXRoIGJlbG93IGl0cyBmYW4tb3V0IHdhbGtzIHRoaXMgY2hhcnQ6XG4gKiBldmVyeSBzZWdtZW50IHRoZSBvbmx5IG1vdW50IG9mIGl0cyBzdWJmbG93IGluIHRoZSBlbmNsb3NpbmcgZ3JhcGgsIGV2ZXJ5XG4gKiBzdWJmbG93IHJlZ2lzdGVyZWQsIGFuZCB0aGUgcGF1c2VkIHN0YWdlIGluIHRoZSBsYXN0IGdyYXBoIOKAlCBjaGVja2VkIGF0XG4gKiB0aGUgRklSU1QgcmVzdW1lLCBzbyBhIHRhbXBlcmVkIHJlY29yZCBpcyByZWZ1c2VkIHVwIGZyb250LCBub3Qgd2hlbiBpdHNcbiAqIHR1cm4gY29tZXMuXG4gKi9cbmZ1bmN0aW9uIHdhbGtzVG9JdHNTdGFnZTxUT3V0LCBUU2NvcGU+KFxuICBjaGFydDogQ2hhcnRJbmRleDxUT3V0LCBUU2NvcGU+LFxuICBzdWJmbG93czogUmVjb3JkPHN0cmluZywgeyByb290OiBTdGFnZU5vZGU8VE91dCwgVFNjb3BlPiB9PiB8IHVuZGVmaW5lZCxcbiAgZmFuT3V0R3JhcGg6IFN0YWdlTm9kZTxUT3V0LCBUU2NvcGU+LFxuICBwYXVzZTogUGVuZGluZ1BhdXNlLFxuICBsZXZlbDogbnVtYmVyLFxuKTogYm9vbGVhbiB7XG4gIGxldCBncmFwaCA9IGZhbk91dEdyYXBoO1xuICBmb3IgKGxldCBpID0gbGV2ZWw7IGkgPCBwYXVzZS5zdWJmbG93UGF0aC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChjaGFydC5tb3VudHNPZihncmFwaCwgcGF1c2Uuc3ViZmxvd1BhdGhbaV0pLmxlbmd0aCAhPT0gMSkgcmV0dXJuIGZhbHNlO1xuICAgIGNvbnN0IGRlZmluaXRpb24gPSBvd25FbnRyeShzdWJmbG93cywgcGF1c2Uuc3ViZmxvd1BhdGhbaV0pO1xuICAgIGlmICghZGVmaW5pdGlvbikgcmV0dXJuIGZhbHNlO1xuICAgIGdyYXBoID0gZGVmaW5pdGlvbi5yb290O1xuICB9XG4gIHJldHVybiBjaGFydC5zdGFnZShncmFwaCwgcGF1c2UucGF1c2VkU3RhZ2VJZCkgIT09IHVuZGVmaW5lZDtcbn1cblxuLyoqIE9uZSBgcGVuZGluZ1BhdXNlc2AgZW50cnksIGNoZWNrZWQgZmllbGQgYnkgZmllbGQg4oCUIGl0IGNvbWVzIGZyb20gc3RvcmVkLCB1bnRydXN0ZWQgZGF0YS4gKi9cbmZ1bmN0aW9uIHZhbGlkUGVuZGluZ1BhdXNlKHJhdzogdW5rbm93biwgbjogbnVtYmVyKTogUGVuZGluZ1BhdXNlIHtcbiAgY29uc3QgcmVmdXNlID0gKHdoYXQ6IHN0cmluZyk6IG5ldmVyID0+IHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgY2hlY2twb2ludDogcGVuZGluZ1BhdXNlc1ske259XSAke3doYXR9LmApO1xuICB9O1xuICBpZiAocmF3ID09PSBudWxsIHx8IHR5cGVvZiByYXcgIT09ICdvYmplY3QnIHx8IEFycmF5LmlzQXJyYXkocmF3KSkgcmVmdXNlKCdtdXN0IGJlIGFuIG9iamVjdCcpO1xuICBjb25zdCByZWNvcmQgPSByYXcgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIGlmICh0eXBlb2YgcmVjb3JkLnBhdXNlZFN0YWdlSWQgIT09ICdzdHJpbmcnIHx8IHJlY29yZC5wYXVzZWRTdGFnZUlkID09PSAnJykge1xuICAgIHJlZnVzZSgnbXVzdCBuYW1lIGl0cyBwYXVzZWQgc3RhZ2UgKHBhdXNlZFN0YWdlSWQsIGEgbm9uLWVtcHR5IHN0cmluZyknKTtcbiAgfVxuICBjb25zdCBzdWJmbG93UGF0aCA9IHJlY29yZC5zdWJmbG93UGF0aDtcbiAgaWYgKCFBcnJheS5pc0FycmF5KHN1YmZsb3dQYXRoKSB8fCAhc3ViZmxvd1BhdGguZXZlcnkoKHMpID0+IHR5cGVvZiBzID09PSAnc3RyaW5nJykpIHtcbiAgICByZWZ1c2UoJ211c3QgY2FycnkgaXRzIHN1YmZsb3dQYXRoIChhbiBhcnJheSBvZiBzdHJpbmdzKScpO1xuICB9XG4gIGNvbnN0IHN0YXRlcyA9IHJlY29yZC5zdWJmbG93U3RhdGVzO1xuICBpZiAoc3RhdGVzICE9PSB1bmRlZmluZWQgJiYgKHN0YXRlcyA9PT0gbnVsbCB8fCB0eXBlb2Ygc3RhdGVzICE9PSAnb2JqZWN0JyB8fCBBcnJheS5pc0FycmF5KHN0YXRlcykpKSB7XG4gICAgcmVmdXNlKCdtdXN0IGNhcnJ5IGl0cyBzdWJmbG93U3RhdGVzIGFzIGFuIG9iamVjdCcpO1xuICB9XG4gIGlmIChyZWNvcmQucGF1c2VkQnkgIT09IHVuZGVmaW5lZCAmJiByZWNvcmQucGF1c2VkQnkgIT09ICdpbnRlcnJ1cHQnKVxuICAgIHJlZnVzZShcImhhcyBhbiB1bmtub3duIHBhdXNlZEJ5IChvbmx5ICdpbnRlcnJ1cHQnKVwiKTtcbiAgcmV0dXJuIHtcbiAgICBwYXVzZWRTdGFnZUlkOiByZWNvcmQucGF1c2VkU3RhZ2VJZCBhcyBzdHJpbmcsXG4gICAgc3ViZmxvd1BhdGg6IHN1YmZsb3dQYXRoIGFzIHN0cmluZ1tdLFxuICAgIHN1YmZsb3dTdGF0ZXM6IChzdGF0ZXMgYXMgUmVjb3JkPHN0cmluZywgUmVjb3JkPHN0cmluZywgdW5rbm93bj4+IHwgdW5kZWZpbmVkKSA/PyB7fSxcbiAgICAuLi4ocmVjb3JkLnBhdXNlRGF0YSAhPT0gdW5kZWZpbmVkICYmIHsgcGF1c2VEYXRhOiByZWNvcmQucGF1c2VEYXRhIH0pLFxuICAgIC4uLihyZWNvcmQucGF1c2VkQnkgPT09ICdpbnRlcnJ1cHQnICYmIHsgcGF1c2VkQnk6ICdpbnRlcnJ1cHQnIGFzIGNvbnN0IH0pLFxuICB9O1xufVxuXG4vKiogYHJlY29yZFtrZXldYCBvbmx5IHdoZW4gaXQgaXMgdGhlIHJlY29yZCdzIE9XTiBwcm9wZXJ0eSDigJQgbmV2ZXIgdGhyb3VnaCB0aGUgcHJvdG90eXBlIGNoYWluLiAqL1xuZnVuY3Rpb24gb3duRW50cnk8VD4ocmVjb3JkOiBSZWNvcmQ8c3RyaW5nLCBUPiB8IHVuZGVmaW5lZCwga2V5OiBzdHJpbmcpOiBUIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIHJlY29yZCAmJiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocmVjb3JkLCBrZXkpID8gcmVjb3JkW2tleV0gOiB1bmRlZmluZWQ7XG59XG4iXX0=