footprintjs 9.17.0 → 9.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +2 -2
- package/dist/esm/lib/memory/utils.d.ts +15 -5
- package/dist/esm/lib/memory/utils.js +37 -9
- package/dist/esm/lib/time-travel/axis.d.ts +119 -0
- package/dist/esm/lib/time-travel/axis.js +179 -0
- package/dist/esm/lib/time-travel/bundles.d.ts +77 -0
- package/dist/esm/lib/time-travel/bundles.js +124 -0
- package/dist/esm/lib/time-travel/chain.d.ts +93 -0
- package/dist/esm/lib/time-travel/chain.js +186 -0
- package/dist/esm/lib/time-travel/commitStops.d.ts +8 -0
- package/dist/esm/lib/time-travel/commitStops.js +9 -1
- package/dist/esm/lib/time-travel/index.d.ts +4 -1
- package/dist/esm/lib/time-travel/index.js +3 -1
- package/dist/esm/lib/time-travel/stateAt.d.ts +39 -10
- package/dist/esm/lib/time-travel/stateAt.js +88 -44
- package/dist/esm/lib/time-travel/timeTravel.d.ts +30 -3
- package/dist/esm/lib/time-travel/timeTravel.js +132 -24
- package/dist/esm/lib/time-travel/types.d.ts +227 -45
- package/dist/esm/lib/time-travel/types.js +1 -1
- package/dist/esm/trace.d.ts +2 -2
- package/dist/esm/trace.js +2 -2
- package/dist/lib/memory/utils.js +39 -11
- package/dist/lib/time-travel/axis.js +184 -0
- package/dist/lib/time-travel/bundles.js +132 -0
- package/dist/lib/time-travel/chain.js +191 -0
- package/dist/lib/time-travel/commitStops.js +9 -1
- package/dist/lib/time-travel/index.js +7 -2
- package/dist/lib/time-travel/stateAt.js +91 -46
- package/dist/lib/time-travel/timeTravel.js +131 -23
- package/dist/lib/time-travel/types.js +1 -1
- package/dist/trace.js +6 -3
- package/dist/types/lib/memory/utils.d.ts +15 -5
- package/dist/types/lib/time-travel/axis.d.ts +119 -0
- package/dist/types/lib/time-travel/bundles.d.ts +77 -0
- package/dist/types/lib/time-travel/chain.d.ts +93 -0
- package/dist/types/lib/time-travel/commitStops.d.ts +8 -0
- package/dist/types/lib/time-travel/index.d.ts +4 -1
- package/dist/types/lib/time-travel/stateAt.d.ts +39 -10
- package/dist/types/lib/time-travel/timeTravel.d.ts +30 -3
- package/dist/types/lib/time-travel/types.d.ts +227 -45
- package/dist/types/trace.d.ts +2 -2
- package/package.json +1 -1
package/CLAUDE.md
CHANGED
|
@@ -17,7 +17,7 @@ Entry points: `footprintjs` (public API) · `/recorders` (factories) · `/trace`
|
|
|
17
17
|
| decide/ | decide()/select() evidence capture |
|
|
18
18
|
| recorder/ | stores (KeyedStore/SequenceStore/BoundaryStateStore), CombinedRecorder routing, built-ins (Topology/InOut/ControlDep/Quality) |
|
|
19
19
|
| slice/ | variable-first backward slicing (triage query layer): sliceForKey (anchor at last writer → causalChain) + arrayProvenance/elementProvenance (append-fold element births — the agent mega-key fix) + KeysReadSource strategies. Pure post-hoc queries; imports memory/ ONLY (see src/lib/slice/README.md) |
|
|
20
|
-
| time-travel/ | the READER'S cursor over a finished trace (9.17.0): `timeTravel()` stops/moves/marks/`drill()`, `stateAt()` fold + honesty basis, `TimeTravelStrategy
|
|
20
|
+
| time-travel/ | the READER'S cursor over a finished trace (9.17.0): `timeTravel()` stops/moves/marks/`drill()`, `stateAt()` fold + honesty basis, `TimeTravelStrategy<TMeta>` seam (one shipped: `commitStops`). 9.18.0 composer's side: axis.ts (`splitAxis` = the ONE guard of the `[start,…stages,end]` contract; `filterStops` = filter + re-partition + `Stop.meta` vocabulary + `Stop.prologue` on an absorbing start — a FLAG, deliberately not a 5th StopKind), bundles.ts (per-bundle narrowing of `unknown[]` rows → index-holding GAPS in `FoldedState.skipped`), chain.ts (`timeTravel([paused, resumed])`: commit indices stay RUN-LOCAL + `Stop.sourceIdx`; refused unless execution indices are monotonic across legs and no id repeats). Read-time only — never a second live cursor. Imports memory/ + `engine/runtimeStageId` (see src/lib/time-travel/README.md) |
|
|
21
21
|
| pause/ | PauseSignal / FlowchartCheckpoint types + `interrupt(scope, payload)` (throws InterruptSignal; converted to PauseSignal at the StageRunner boundary, `pausedBy:'interrupt'`) |
|
|
22
22
|
| engine/ | FlowchartTraverser + handlers/; narrative/ = the whole FlowRecorder channel (dispatcher + 9 strategies), not just text; branchSegment.ts = the ONE owner of the generated-segment grammar (`<stageId>~<index>`, marker `~` RESERVED); `executeStage` (:720) = the ONE funnel every stage fn passes through — and therefore the ONE owner of the declarative `retry` loop |
|
|
23
23
|
| runner/ | FlowChartExecutor wiring (runtime, recorders, pause/resume, snapshot, DeferredObserverTier). RunContext.ts is a fluent run builder, NOT the threaded per-run context |
|
|
@@ -66,7 +66,7 @@ loop: Phase 6 sees isLoopRef → ContinuationResolver.resolveTarget (:107): id-m
|
|
|
66
66
|
end: onRunEnd (throw → onRunFailed; pause → neither) → deferred terminalFlush → getSnapshot() = {sharedState (LIVE view; dev-mode frozen clone), initialState (the fold base), commitLog (detached+frozen), executionTree, subflowResults (dual-keyed), recorders}.
|
|
67
67
|
|
|
68
68
|
## Backtracking
|
|
69
|
-
Seven mechanisms, no state rollback anywhere: **M1** TransactionBuffer staging + net-change commit — commit-on-error by design, explicitly NOT rollback (TransactionBuffer.ts:13-18; error path commits then rethrows). **M2** Pause/Resume checkpointing — the only resume-from-prior-point; TWO raise shapes, ONE checkpoint: `addPausableFunction` (resume runs `resumeFn`) and `interrupt(scope, payload)` (resume RE-RUNS THE STAGE FUNCTION FROM ITS TOP — stages are atomic; the answer returns out of the `interrupt()` call via a WeakMap keyed by the scope), discriminated by `checkpoint.pausedBy`; checkpoint is one detached structuredClone; resume rebuilds the cursor from pausedStageId+subflowPath and only overrides the LEAF subflow root (2+-deep pause re-executes outer pre-mount stages). **M3** commit-log replay (EventLog.materialise, commitValueAt — required under delta mode). **M4** loopTo re-entry — forward execution over accumulated state, bounded by maxIterations + dynamicNextHops. **M5** causalChain backward slicing (read-only analysis; honesty flags for untracked reads; `edgeAttribution: 'per-write'` refines edges via `TraceEntry.readKeys` when the writeProvenance dial recorded them — worklist, subset-of-ceiling safe). **M6 (query layer)** slice/ — variable-first triage: sliceForKey + append-fold element provenance + the ONLY safe serializations (sliceToJSON/formatSlice — never JSON.stringify a slice root). **M7 (read-time cursor)** time-travel/ — `timeTravel(snapshot)` walks stops over the finished log with `stateAt()` folding M3's replay at each one (base = `RuntimeSnapshot.initialState`, which now travels with the log); it is a READER, never a second live cursor, and `drill(mount)` opens a separate cursor over a subflow's own isolated log. Deep dive + step tables: [.claude/rules/backtracking.md](.claude/rules/backtracking.md).
|
|
69
|
+
Seven mechanisms, no state rollback anywhere: **M1** TransactionBuffer staging + net-change commit — commit-on-error by design, explicitly NOT rollback (TransactionBuffer.ts:13-18; error path commits then rethrows). **M2** Pause/Resume checkpointing — the only resume-from-prior-point; TWO raise shapes, ONE checkpoint: `addPausableFunction` (resume runs `resumeFn`) and `interrupt(scope, payload)` (resume RE-RUNS THE STAGE FUNCTION FROM ITS TOP — stages are atomic; the answer returns out of the `interrupt()` call via a WeakMap keyed by the scope), discriminated by `checkpoint.pausedBy`; checkpoint is one detached structuredClone; resume rebuilds the cursor from pausedStageId+subflowPath and only overrides the LEAF subflow root (2+-deep pause re-executes outer pre-mount stages). **M3** commit-log replay (EventLog.materialise, commitValueAt — required under delta mode). **M4** loopTo re-entry — forward execution over accumulated state, bounded by maxIterations + dynamicNextHops. **M5** causalChain backward slicing (read-only analysis; honesty flags for untracked reads; `edgeAttribution: 'per-write'` refines edges via `TraceEntry.readKeys` when the writeProvenance dial recorded them — worklist, subset-of-ceiling safe). **M6 (query layer)** slice/ — variable-first triage: sliceForKey + append-fold element provenance + the ONLY safe serializations (sliceToJSON/formatSlice — never JSON.stringify a slice root). **M7 (read-time cursor)** time-travel/ — `timeTravel(snapshot)` walks stops over the finished log with `stateAt()` folding M3's replay at each one (base = `RuntimeSnapshot.initialState`, which now travels with the log); it is a READER, never a second live cursor, and `drill(mount)` opens a separate cursor over a subflow's own isolated log. 9.18.0: `timeTravel([paused, resumed])` chains a cross-executor M2 resume into ONE axis — the resumed leg's `initialState` (= the state at the pause) restarts the fold, commit indices stay run-local (`Stop.sourceIdx` names the leg), and the chain is refused unless the never-reset execution counter is monotonic across legs. Deep dive + step tables: [.claude/rules/backtracking.md](.claude/rules/backtracking.md).
|
|
70
70
|
|
|
71
71
|
## Invariants (assumed, not stated)
|
|
72
72
|
- Committed state immutable-after-swap; first-touch views hold bare references on that guarantee — in-place mutation of SharedMemory.context corrupts every in-flight stage.
|
|
@@ -79,11 +79,13 @@ export declare function normalisePath(path: (string | number)[]): string;
|
|
|
79
79
|
* - Primitive comparisons (the bulk of state) are O(1) via the `===` /
|
|
80
80
|
* `Object.is` fast paths; only nested objects/arrays incur a walk, bounded
|
|
81
81
|
* by the value's own size.
|
|
82
|
-
* -
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
82
|
+
* - Terminates on CYCLIC values (9.18.1): a state value must survive
|
|
83
|
+
* `structuredClone`, and `structuredClone` preserves cycles — so a
|
|
84
|
+
* self-referencing value is a legal value, not an out-of-contract one. A
|
|
85
|
+
* pair of objects already under comparison is treated as equal (the
|
|
86
|
+
* structural answer, lodash `isEqual` semantics); acyclic inputs see no
|
|
87
|
+
* change. Dev mode still warns about cycles at write time
|
|
88
|
+
* (`ScopeFacade.setValue`) because they surprise narrative and JSON.
|
|
87
89
|
*/
|
|
88
90
|
export declare function deepEqual(a: any, b: any): boolean;
|
|
89
91
|
/**
|
|
@@ -95,6 +97,14 @@ export declare function deepEqual(a: any, b: any): boolean;
|
|
|
95
97
|
* impossible to distinguish from a bug.
|
|
96
98
|
* - Objects: recursive merge
|
|
97
99
|
* - Primitives: source wins
|
|
100
|
+
*
|
|
101
|
+
* Terminates on a CYCLIC `src` (9.18.1, same law as {@link deepEqual}: a
|
|
102
|
+
* state value survives `structuredClone`, which preserves cycles). A `src`
|
|
103
|
+
* object re-entered while it is still being merged higher up the stack hands
|
|
104
|
+
* back the output being built for it, so the merged value mirrors the cycle
|
|
105
|
+
* instead of unrolling it forever. Only the ancestors on the stack are
|
|
106
|
+
* guarded — a shared (acyclic) `src` reference met again at a different
|
|
107
|
+
* `dst` merges against THAT `dst`, exactly as before.
|
|
98
108
|
*/
|
|
99
109
|
export declare function deepSmartMerge(dst: any, src: any): any;
|
|
100
110
|
/**
|
|
@@ -145,13 +145,18 @@ export function normalisePath(path) {
|
|
|
145
145
|
* - Primitive comparisons (the bulk of state) are O(1) via the `===` /
|
|
146
146
|
* `Object.is` fast paths; only nested objects/arrays incur a walk, bounded
|
|
147
147
|
* by the value's own size.
|
|
148
|
-
* -
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
148
|
+
* - Terminates on CYCLIC values (9.18.1): a state value must survive
|
|
149
|
+
* `structuredClone`, and `structuredClone` preserves cycles — so a
|
|
150
|
+
* self-referencing value is a legal value, not an out-of-contract one. A
|
|
151
|
+
* pair of objects already under comparison is treated as equal (the
|
|
152
|
+
* structural answer, lodash `isEqual` semantics); acyclic inputs see no
|
|
153
|
+
* change. Dev mode still warns about cycles at write time
|
|
154
|
+
* (`ScopeFacade.setValue`) because they surprise narrative and JSON.
|
|
153
155
|
*/
|
|
154
156
|
export function deepEqual(a, b) {
|
|
157
|
+
return equalPairs(a, b, undefined);
|
|
158
|
+
}
|
|
159
|
+
function equalPairs(a, b, seen) {
|
|
155
160
|
if (a === b)
|
|
156
161
|
return true; // same reference or identical primitive
|
|
157
162
|
if (typeof a !== typeof b)
|
|
@@ -163,11 +168,19 @@ export function deepEqual(a, b) {
|
|
|
163
168
|
const aIsArray = Array.isArray(a);
|
|
164
169
|
if (aIsArray !== Array.isArray(b))
|
|
165
170
|
return false; // array vs plain object
|
|
171
|
+
// Cycle guard — a pair we are already inside is equal by assumption.
|
|
172
|
+
seen ??= new WeakMap();
|
|
173
|
+
let partners = seen.get(a);
|
|
174
|
+
if (partners?.has(b))
|
|
175
|
+
return true;
|
|
176
|
+
if (!partners)
|
|
177
|
+
seen.set(a, (partners = new WeakSet()));
|
|
178
|
+
partners.add(b);
|
|
166
179
|
if (aIsArray) {
|
|
167
180
|
if (a.length !== b.length)
|
|
168
181
|
return false;
|
|
169
182
|
for (let i = 0; i < a.length; i++) {
|
|
170
|
-
if (!
|
|
183
|
+
if (!equalPairs(a[i], b[i], seen))
|
|
171
184
|
return false;
|
|
172
185
|
}
|
|
173
186
|
return true;
|
|
@@ -179,7 +192,7 @@ export function deepEqual(a, b) {
|
|
|
179
192
|
for (const key of aKeys) {
|
|
180
193
|
if (!Object.prototype.hasOwnProperty.call(b, key))
|
|
181
194
|
return false;
|
|
182
|
-
if (!
|
|
195
|
+
if (!equalPairs(a[key], b[key], seen))
|
|
183
196
|
return false;
|
|
184
197
|
}
|
|
185
198
|
return true;
|
|
@@ -193,8 +206,19 @@ export function deepEqual(a, b) {
|
|
|
193
206
|
* impossible to distinguish from a bug.
|
|
194
207
|
* - Objects: recursive merge
|
|
195
208
|
* - Primitives: source wins
|
|
209
|
+
*
|
|
210
|
+
* Terminates on a CYCLIC `src` (9.18.1, same law as {@link deepEqual}: a
|
|
211
|
+
* state value survives `structuredClone`, which preserves cycles). A `src`
|
|
212
|
+
* object re-entered while it is still being merged higher up the stack hands
|
|
213
|
+
* back the output being built for it, so the merged value mirrors the cycle
|
|
214
|
+
* instead of unrolling it forever. Only the ancestors on the stack are
|
|
215
|
+
* guarded — a shared (acyclic) `src` reference met again at a different
|
|
216
|
+
* `dst` merges against THAT `dst`, exactly as before.
|
|
196
217
|
*/
|
|
197
218
|
export function deepSmartMerge(dst, src) {
|
|
219
|
+
return mergeGuarded(dst, src, undefined);
|
|
220
|
+
}
|
|
221
|
+
function mergeGuarded(dst, src, inFlight) {
|
|
198
222
|
if (src === null || typeof src !== 'object')
|
|
199
223
|
return src;
|
|
200
224
|
if (Array.isArray(src)) {
|
|
@@ -204,11 +228,15 @@ export function deepSmartMerge(dst, src) {
|
|
|
204
228
|
return [...new Set([...dst, ...src])];
|
|
205
229
|
return [...src];
|
|
206
230
|
}
|
|
231
|
+
if (inFlight?.has(src))
|
|
232
|
+
return inFlight.get(src); // cycle — re-enter the value being built
|
|
207
233
|
const out = { ...(dst && typeof dst === 'object' ? dst : {}) };
|
|
234
|
+
(inFlight ??= new WeakMap()).set(src, out);
|
|
208
235
|
// Object.keys() is own-enumerable-only by spec — no DENIED check needed here.
|
|
209
236
|
for (const k of Object.keys(src)) {
|
|
210
|
-
out[k] =
|
|
237
|
+
out[k] = mergeGuarded(out[k], src[k], inFlight);
|
|
211
238
|
}
|
|
239
|
+
inFlight.delete(src);
|
|
212
240
|
return out;
|
|
213
241
|
}
|
|
214
242
|
/**
|
|
@@ -256,4 +284,4 @@ export function applySmartMerge(base, updates, overwrite, trace) {
|
|
|
256
284
|
}
|
|
257
285
|
return out;
|
|
258
286
|
}
|
|
259
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL21lbW9yeS91dGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7R0FLRztBQUVILE9BQU8sRUFBRSxZQUFZLEVBQUUsU0FBUyxJQUFJLElBQUksRUFBRSxTQUFTLElBQUksSUFBSSxFQUFFLFNBQVMsSUFBSSxJQUFJLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFHckcsaUZBQWlGO0FBQ2pGLE1BQU0sQ0FBQyxNQUFNLEtBQUssR0FBRyxRQUFRLENBQUM7QUFJOUI7OztHQUdHO0FBQ0gsTUFBTSxVQUFVLG9CQUFvQixDQUFDLEtBQWMsRUFBRSxPQUE0QixFQUFFO0lBQ2pGLE9BQU87UUFDTCxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUztRQUNyRCxVQUFVLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQztLQUN0QixDQUFDO0FBQ0osQ0FBQztBQUVEOztHQUVHO0FBQ0gsTUFBTSxVQUFVLGNBQWMsQ0FDNUIsR0FBaUIsRUFDakIsS0FBYSxFQUNiLEtBQWUsRUFDZixLQUFhLEVBQ2IsS0FBUSxFQUNSLGFBQXVCO0lBRXZCLE1BQU0sRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLEdBQUcsb0JBQW9CLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ25FLE1BQU0sSUFBSSxHQUFHLE9BQU8sSUFBSSxVQUFVLENBQUM7SUFDbkMsTUFBTSxRQUFRLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQzNCLElBQUksT0FBTyxHQUFpQixHQUFHLENBQUM7SUFDaEMsT0FBTyxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQzNCLE1BQU0sR0FBRyxHQUFHLFFBQVEsQ0FBQyxLQUFLLEVBQVksQ0FBQztRQUN2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RCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQ2hDLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLE9BQU8sRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNoRyxDQUFDO2FBQU0sSUFBSSxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDN0IsWUFBWSxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUMxQixDQUFDO2FBQU0sQ0FBQztZQUNOLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ3RDLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLGNBQWMsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDaEUsQ0FBQztJQUNILENBQUM7SUFDRCxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIHV0aWxzLnRzIOKAlCBIZWxwZXIgZnVuY3Rpb25zIGZvciBuZXN0ZWQgb2JqZWN0IG1hbmlwdWxhdGlvblxuICpcbiAqIFByb3ZpZGVzIGNvbnNpc3RlbnQgcGF0aCB0cmF2ZXJzYWwgYW5kIHZhbHVlIG1hbmlwdWxhdGlvbiBmb3IgdGhlIG1lbW9yeSBzeXN0ZW0uXG4gKiBaZXJvIGV4dGVybmFsIGRlcGVuZGVuY2llcy5cbiAqL1xuXG5pbXBvcnQgeyBuYXRpdmVEZWxldGUsIG5hdGl2ZUdldCBhcyBfZ2V0LCBuYXRpdmVIYXMgYXMgX2hhcywgbmF0aXZlU2V0IGFzIF9zZXQgfSBmcm9tICcuL3BhdGhPcHMuanMnO1xuaW1wb3J0IHR5cGUgeyBNZW1vcnlQYXRjaCwgVHJhY2VFbnRyeSB9IGZyb20gJy4vdHlwZXMuanMnO1xuXG4vKiogQVNDSUkgVW5pdC1TZXBhcmF0b3Ig4oCUIGNhbm5vdCBhcHBlYXIgaW4gSlMgaWRlbnRpZmllcnMsIGludmlzaWJsZSBpbiBsb2dzLiAqL1xuZXhwb3J0IGNvbnN0IERFTElNID0gJ1xcdTAwMUYnO1xuXG50eXBlIE5lc3RlZE9iamVjdCA9IHsgW2tleTogc3RyaW5nXTogYW55IH07XG5cbi8qKlxuICogUmVzb2x2ZXMgcnVuLW5hbWVzcGFjZWQgYW5kIGdsb2JhbCBwYXRocy5cbiAqIEVhY2ggZmxvd2NoYXJ0IGV4ZWN1dGlvbiAocnVuKSBzdG9yZXMgZGF0YSB1bmRlciBgcnVucy97aWR9L2AgdG8gcHJldmVudCBjb2xsaXNpb25zLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0UnVuQW5kR2xvYmFsUGF0aHMocnVuSWQ/OiBzdHJpbmcsIHBhdGg6IChzdHJpbmcgfCBudW1iZXIpW10gPSBbXSkge1xuICByZXR1cm4ge1xuICAgIHJ1blBhdGg6IHJ1bklkID8gWydydW5zJywgcnVuSWQsIC4uLnBhdGhdIDogdW5kZWZpbmVkLFxuICAgIGdsb2JhbFBhdGg6IFsuLi5wYXRoXSxcbiAgfTtcbn1cblxuLyoqXG4gKiBTZXRzIGEgdmFsdWUgYXQgYSBuZXN0ZWQgcGF0aCwgY3JlYXRpbmcgaW50ZXJtZWRpYXRlIG9iamVjdHMgYXMgbmVlZGVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0TmVzdGVkVmFsdWU8VD4oXG4gIG9iajogTmVzdGVkT2JqZWN0LFxuICBydW5JZDogc3RyaW5nLFxuICBfcGF0aDogc3RyaW5nW10sXG4gIGZpZWxkOiBzdHJpbmcsXG4gIHZhbHVlOiBULFxuICBkZWZhdWx0VmFsdWVzPzogdW5rbm93bixcbik6IE5lc3RlZE9iamVjdCB7XG4gIGNvbnN0IHsgcnVuUGF0aCwgZ2xvYmFsUGF0aCB9ID0gZ2V0UnVuQW5kR2xvYmFsUGF0aHMocnVuSWQsIF9wYXRoKTtcbiAgY29uc3QgcGF0aCA9IHJ1blBhdGggfHwgZ2xvYmFsUGF0aDtcbiAgY29uc3QgcGF0aENvcHkgPSBbLi4ucGF0aF07XG4gIGxldCBjdXJyZW50OiBOZXN0ZWRPYmplY3QgPSBvYmo7XG4gIHdoaWxlIChwYXRoQ29weS5sZW5ndGggPiAwKSB7XG4gICAgY29uc3Qga2V5ID0gcGF0aENvcHkuc2hpZnQoKSBhcyBzdHJpbmc7XG4gICAgaWYgKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoY3VycmVudCwga2V5KSkge1xuICAgICAgY3VycmVudFtrZXldID0ga2V5ID09PSBydW5JZCAmJiBkZWZhdWx0VmFsdWVzID8gZGVmYXVsdFZhbHVlcyA6IHt9O1xuICAgIH1cbiAgICBjdXJyZW50ID0gY3VycmVudFtrZXldO1xuICB9XG4gIGN1cnJlbnRbZmllbGRdID0gdmFsdWU7XG4gIHJldHVybiBvYmo7XG59XG5cbi8qKlxuICogRGVlcC1tZXJnZXMgYSB2YWx1ZSBpbnRvIHRoZSBvYmplY3QgYXQgdGhlIHNwZWNpZmllZCBwYXRoLlxuICogLSBBcnJheXM6IGNvbmNhdGVuYXRlXG4gKiAtIE9iamVjdHM6IHNoYWxsb3cgbWVyZ2UgYXQgZWFjaCBsZXZlbFxuICogLSBQcmltaXRpdmVzOiByZXBsYWNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1cGRhdGVOZXN0ZWRWYWx1ZTxUPihcbiAgb2JqOiBhbnksXG4gIHJ1bklkOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gIF9wYXRoOiAoc3RyaW5nIHwgbnVtYmVyKVtdLFxuICBmaWVsZDogc3RyaW5nIHwgbnVtYmVyLFxuICB2YWx1ZTogVCxcbiAgZGVmYXVsdFZhbHVlcz86IHVua25vd24sXG4pOiBhbnkge1xuICBjb25zdCB7IHJ1blBhdGgsIGdsb2JhbFBhdGggfSA9IGdldFJ1bkFuZEdsb2JhbFBhdGhzKHJ1bklkLCBfcGF0aCk7XG4gIGNvbnN0IHBhdGggPSBydW5QYXRoIHx8IGdsb2JhbFBhdGg7XG4gIGNvbnN0IHBhdGhDb3B5ID0gWy4uLnBhdGhdO1xuICBsZXQgY3VycmVudDogTmVzdGVkT2JqZWN0ID0gb2JqO1xuICB3aGlsZSAocGF0aENvcHkubGVuZ3RoID4gMCkge1xuICAgIGNvbnN0IGtleSA9IHBhdGhDb3B5LnNoaWZ0KCkgYXMgc3RyaW5nO1xuICAgIGlmICghT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGN1cnJlbnQsIGtleSkpIHtcbiAgICAgIGN1cnJlbnRba2V5XSA9IGtleSA9PT0gcnVuSWQgJiYgZGVmYXVsdFZhbHVlcyA/IGRlZmF1bHRWYWx1ZXMgOiB7fTtcbiAgICB9XG4gICAgY3VycmVudCA9IGN1cnJlbnRba2V5XTtcbiAgfVxuICB1cGRhdGVWYWx1ZShjdXJyZW50LCBmaWVsZCwgdmFsdWUpO1xuICByZXR1cm4gb2JqO1xufVxuXG4vKipcbiAqIEluLXBsYWNlIHZhbHVlIHVwZGF0ZSB3aXRoIG1lcmdlIHNlbWFudGljcy5cbiAqIC0gQXJyYXlzIChub24tZW1wdHkpOiBjb25jYXRlbmF0ZSBvbnRvIGV4aXN0aW5nXG4gKiAtIEFycmF5cyAoZW1wdHkpOiAgICAgZGlyZWN0IHJlcGxhY2Ug4oCUIHdyaXRpbmcgYFtdYCBjbGVhcnMgdGhlIGZpZWxkXG4gKiAtIE9iamVjdHMgKG5vbi1lbXB0eSk6IHNoYWxsb3cgbWVyZ2UgKHNwcmVhZClcbiAqIC0gT2JqZWN0cyAoZW1wdHkpOiAgICBkaXJlY3QgcmVwbGFjZSDigJQgd3JpdGluZyBge31gIGNsZWFycyB0aGUgZmllbGRcbiAqIC0gUHJpbWl0aXZlczogZGlyZWN0IGFzc2lnbm1lbnRcbiAqXG4gKiBOb3RlIG9uIGVtcHR5IGFycmF5czogYm90aCBgdmFsdWUgJiYgQXJyYXkuaXNBcnJheSh2YWx1ZSlgIGFuZFxuICogYEFycmF5LmlzQXJyYXkodmFsdWUpYCBldmFsdWF0ZSB0aGUgc2FtZSBmb3IgYXJyYXlzIOKAlCBgW11gIGlzIHRydXRoeSBpblxuICogSmF2YVNjcmlwdCwgc28gdGhlIGAmJmAgZ3VhcmQgd2FzIG5ldmVyIHRoZSBpc3N1ZS4gVGhlIGFjdHVhbCBidWcgd2FzIHRoZVxuICogY29uY2F0IHBhdGg6IGBbLi4uY3VyLCAuLi5bXV1gIHNpbGVudGx5IHJldHVybmVkIGBjdXJgIHVuY2hhbmdlZCB3aGVuIGB2YWx1ZWBcbiAqIHdhcyBgW11gLCBtYWtpbmcgYHVwZGF0ZVZhbHVlKG9iaiwgJ3RhZ3MnLCBbXSlgIGEgbm8tb3AgaW5zdGVhZCBvZiBhIGNsZWFyLlxuICogVGhlIGZpeCBpcyB0aGUgZXhwbGljaXQgYHZhbHVlLmxlbmd0aCA9PT0gMGAgZWFybHktcmV0dXJuIGJyYW5jaC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZVZhbHVlKG9iamVjdDogYW55LCBrZXk6IHN0cmluZyB8IG51bWJlciwgdmFsdWU6IGFueSk6IHZvaWQge1xuICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICBpZiAodmFsdWUubGVuZ3RoID09PSAwKSB7XG4gICAgICBvYmplY3Rba2V5XSA9IHZhbHVlOyAvLyBjbGVhcjogW10gcmVwbGFjZXMgd2hhdGV2ZXIgd2FzIHRoZXJlXG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGN1ciA9IG9iamVjdFtrZXldIGFzIGFueTtcbiAgICAgIG9iamVjdFtrZXldID0gY3VyID09PSB1bmRlZmluZWQgPyB2YWx1ZSA6IFsuLi5jdXIsIC4uLnZhbHVlXTtcbiAgICB9XG4gIH0gZWxzZSBpZiAodmFsdWUgJiYgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiBPYmplY3Qua2V5cyh2YWx1ZSkubGVuZ3RoKSB7XG4gICAgY29uc3QgY3VyID0gb2JqZWN0W2tleV0gYXMgYW55O1xuICAgIG9iamVjdFtrZXldID0gY3VyID09PSB1bmRlZmluZWQgPyB2YWx1ZSA6IHsgLi4uY3VyLCAuLi52YWx1ZSB9O1xuICB9IGVsc2Uge1xuICAgIG9iamVjdFtrZXldID0gdmFsdWU7XG4gIH1cbn1cblxuLyoqXG4gKiBHZXRzIGEgdmFsdWUgYXQgYSBuZXN0ZWQgcGF0aCB3aXRoIHByb3RvdHlwZS1wb2xsdXRpb24gcHJvdGVjdGlvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldE5lc3RlZFZhbHVlKHJvb3Q6IGFueSwgcGF0aDogKHN0cmluZyB8IG51bWJlcilbXSwgZmllbGQ/OiBzdHJpbmcgfCBudW1iZXIpOiBhbnkge1xuICBjb25zdCBub2RlID0gcGF0aCAmJiBwYXRoLmxlbmd0aCA+IDAgPyBfZ2V0KHJvb3QsIHBhdGgpIDogcm9vdDtcbiAgaWYgKGZpZWxkID09PSB1bmRlZmluZWQgfHwgbm9kZSA9PT0gdW5kZWZpbmVkKSByZXR1cm4gbm9kZTtcbiAgaWYgKG5vZGUgIT09IG51bGwgJiYgdHlwZW9mIG5vZGUgPT09ICdvYmplY3QnICYmIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChub2RlLCBmaWVsZCkpIHtcbiAgICByZXR1cm4gbm9kZVtmaWVsZF07XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBSZWRhY3RzIHNlbnNpdGl2ZSB2YWx1ZXMgaW4gYSBwYXRjaCBmb3IgbG9nZ2luZy9kZWJ1Z2dpbmcuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWRhY3RQYXRjaChwYXRjaDogTWVtb3J5UGF0Y2gsIHJlZGFjdGVkU2V0OiBTZXQ8c3RyaW5nPik6IE1lbW9yeVBhdGNoIHtcbiAgY29uc3Qgb3V0ID0gc3RydWN0dXJlZENsb25lKHBhdGNoKTtcbiAgZm9yIChjb25zdCBmbGF0IG9mIHJlZGFjdGVkU2V0KSB7XG4gICAgY29uc3QgcGF0aEFyciA9IGZsYXQuc3BsaXQoREVMSU0pO1xuICAgIGlmIChfaGFzKG91dCwgcGF0aEFycikpIHtcbiAgICAgIGNvbnN0IGN1cnIgPSBfZ2V0KG91dCwgcGF0aEFycik7XG4gICAgICBpZiAodHlwZW9mIGN1cnIgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIF9zZXQob3V0LCBwYXRoQXJyLCAnUkVEQUNURUQnKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIG91dDtcbn1cblxuLyoqXG4gKiBOb3JtYWxpc2VzIGFuIGFycmF5IHBhdGggaW50byBhIHN0YWJsZSBzdHJpbmcga2V5IHVzaW5nIERFTElNLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbm9ybWFsaXNlUGF0aChwYXRoOiAoc3RyaW5nIHwgbnVtYmVyKVtdKTogc3RyaW5nIHtcbiAgcmV0dXJuIHBhdGgubWFwKFN0cmluZykuam9pbihERUxJTSk7XG59XG5cbi8qKlxuICogU3RydWN0dXJhbCBkZWVwIGVxdWFsaXR5IGZvciBjb21taXR0ZWQtc3RhdGUgdmFsdWVzLlxuICpcbiAqIFVzZWQgYnkge0BsaW5rIFRyYW5zYWN0aW9uQnVmZmVyfSB0byBkZWNpZGUgd2hldGhlciBhIHN0YWdlIGFjdHVhbGx5IENIQU5HRURcbiAqIGEgcGF0aCBvciBtZXJlbHkgcmUtd3JvdGUgLyByZXZlcnRlZCBpdCB0byB0aGUgdmFsdWUgaXQgYWxyZWFkeSBoZWxkIChhXG4gKiBcIm5vLW9wIHdyaXRlXCIpLiBDb21taXR0ZWQgc3RhdGUgaXMgSlNPTi1zaGFwZWQg4oCUIGl0IG11c3Qgc3Vydml2ZVxuICogYHN0cnVjdHVyZWRDbG9uZWAg4oCUIHNvIHRoaXMgb25seSBuZWVkcyB0byBoYW5kbGUgdGhlIHNoYXBlcyB0aGF0IGNhbiByZWFjaCBhXG4gKiBjb21taXQ6IHByaW1pdGl2ZXMsIGFycmF5cywgYW5kIHBsYWluIG9iamVjdHMuXG4gKlxuICogU2VtYW50aWNzOlxuICogICAtIHJlZmVyZW5jZSAvIGlkZW50aWNhbC1wcmltaXRpdmUgc2hvcnQtY2lyY3VpdHMgZmlyc3QgKGNoZWFwIGZhc3QgcGF0aClcbiAqICAgLSBgTmFOYCBlcXVhbHMgYE5hTmAgKHByaW1pdGl2ZSBjb21wYXJlIGZhbGxzIGJhY2sgdG8gYE9iamVjdC5pc2ApXG4gKiAgIC0gYXJyYXlzOiBlcXVhbCBsZW5ndGggQU5EIGRlZXAtZXF1YWwgZWxlbWVudC13aXNlIChvcmRlci1zZW5zaXRpdmUpXG4gKiAgIC0gb2JqZWN0czogaWRlbnRpY2FsIG93bi1rZXkgc2V0IEFORCBkZWVwLWVxdWFsIHBlciBrZXlcbiAqICAgLSBtaXNtYXRjaGVkIGtpbmRzIChhcnJheSB2cyBvYmplY3QsIG9iamVjdCB2cyBudWxsKSDihpIgbm90IGVxdWFsXG4gKlxuICogQ29zdCAmIHNhZmV0eTpcbiAqICAgLSBBbGxvY2F0ZXMgTk9USElORyBidXQgdHJhbnNpZW50IGBPYmplY3Qua2V5c2AgYXJyYXlzIOKAlCBubyBjbG9uZXMuIEl0IGlzXG4gKiAgICAgc3RyaWN0bHkgY2hlYXBlciB0aGFuIHRoZSBgc3RydWN0dXJlZENsb25lYCB0aGUgY29tbWl0IGFscmVhZHkgcGVyZm9ybXMuXG4gKiAgIC0gUHJpbWl0aXZlIGNvbXBhcmlzb25zICh0aGUgYnVsayBvZiBzdGF0ZSkgYXJlIE8oMSkgdmlhIHRoZSBgPT09YCAvXG4gKiAgICAgYE9iamVjdC5pc2AgZmFzdCBwYXRoczsgb25seSBuZXN0ZWQgb2JqZWN0cy9hcnJheXMgaW5jdXIgYSB3YWxrLCBib3VuZGVkXG4gKiAgICAgYnkgdGhlIHZhbHVlJ3Mgb3duIHNpemUuXG4gKiAgIC0gQXNzdW1lcyBBQ1lDTElDLCBKU09OLXNoYXBlZCB2YWx1ZXMg4oCUIHRoZSBzYW1lIGNvbnRyYWN0IHRoZSBtZW1vcnkgbGF5ZXJcbiAqICAgICBhbHJlYWR5IHJlbGllcyBvbiAoY29tbWl0dGVkIHN0YXRlIGlzIGBzdHJ1Y3R1cmVkQ2xvbmVgZCBhbmQgbXVzdCBiZVxuICogICAgIEpTT04tc2VyaWFsaXNhYmxlIGZvciBjaGVja3BvaW50cykuIEEgY3ljbGljIHZhbHVlIGlzIG91dCBvZiBjb250cmFjdFxuICogICAgIGhlcmUgZXhhY3RseSBhcyBpdCBpcyBmb3IgY2hlY2twb2ludGluZzsgZGV2IG1vZGUgZmxhZ3MgY3ljbGVzIGF0IHdyaXRlXG4gKiAgICAgdGltZSB2aWEgYFNjb3BlRmFjYWRlLnNldFZhbHVlYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlZXBFcXVhbChhOiBhbnksIGI6IGFueSk6IGJvb2xlYW4ge1xuICBpZiAoYSA9PT0gYikgcmV0dXJuIHRydWU7IC8vIHNhbWUgcmVmZXJlbmNlIG9yIGlkZW50aWNhbCBwcmltaXRpdmVcbiAgaWYgKHR5cGVvZiBhICE9PSB0eXBlb2YgYikgcmV0dXJuIGZhbHNlO1xuICBpZiAoYSA9PT0gbnVsbCB8fCBiID09PSBudWxsKSByZXR1cm4gYSA9PT0gYjsgLy8gb25lIGlzIG51bGwsIHRoZSBvdGhlciBpc24ndFxuICBpZiAodHlwZW9mIGEgIT09ICdvYmplY3QnKSByZXR1cm4gT2JqZWN0LmlzKGEsIGIpOyAvLyBOYU4tc2FmZSBwcmltaXRpdmUgY29tcGFyZVxuXG4gIGNvbnN0IGFJc0FycmF5ID0gQXJyYXkuaXNBcnJheShhKTtcbiAgaWYgKGFJc0FycmF5ICE9PSBBcnJheS5pc0FycmF5KGIpKSByZXR1cm4gZmFsc2U7IC8vIGFycmF5IHZzIHBsYWluIG9iamVjdFxuXG4gIGlmIChhSXNBcnJheSkge1xuICAgIGlmIChhLmxlbmd0aCAhPT0gYi5sZW5ndGgpIHJldHVybiBmYWxzZTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGEubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmICghZGVlcEVxdWFsKGFbaV0sIGJbaV0pKSByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgY29uc3QgYUtleXMgPSBPYmplY3Qua2V5cyhhKTtcbiAgY29uc3QgYktleXMgPSBPYmplY3Qua2V5cyhiKTtcbiAgaWYgKGFLZXlzLmxlbmd0aCAhPT0gYktleXMubGVuZ3RoKSByZXR1cm4gZmFsc2U7XG4gIGZvciAoY29uc3Qga2V5IG9mIGFLZXlzKSB7XG4gICAgaWYgKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwga2V5KSkgcmV0dXJuIGZhbHNlO1xuICAgIGlmICghZGVlcEVxdWFsKGFba2V5XSwgYltrZXldKSkgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiB0cnVlO1xufVxuXG4vKipcbiAqIERlZXAgdW5pb24gbWVyZ2UgaGVscGVyLlxuICogLSBBcnJheXMgKG5vbi1lbXB0eSk6IHVuaW9uIHdpdGhvdXQgZHVwbGljYXRlcyAoZW5jb3VudGVyIG9yZGVyIHByZXNlcnZlZClcbiAqIC0gQXJyYXlzIChlbXB0eSk6ICAgICByZXBsYWNlIOKAlCBzcmMgYFtdYCBjbGVhcnMgdGhlIGRlc3RpbmF0aW9uIGFycmF5LlxuICogICBSYXRpb25hbGU6IHdyaXRpbmcgYHNjb3BlLnRhZ3MgPSBbXWAgbWVhbnMgXCJjbGVhciB0YWdzXCIsIG5vdCBcImFwcGVuZCBub3RoaW5nXCIuXG4gKiAgIFdpdGhvdXQgdGhpcyBydWxlLCBhbiBlbXB0eS1hcnJheSB3cml0ZSBzaWxlbnRseSBiZWNvbWVzIGEgbm8tb3Agd2hpY2ggaXNcbiAqICAgaW1wb3NzaWJsZSB0byBkaXN0aW5ndWlzaCBmcm9tIGEgYnVnLlxuICogLSBPYmplY3RzOiByZWN1cnNpdmUgbWVyZ2VcbiAqIC0gUHJpbWl0aXZlczogc291cmNlIHdpbnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlZXBTbWFydE1lcmdlKGRzdDogYW55LCBzcmM6IGFueSk6IGFueSB7XG4gIGlmIChzcmMgPT09IG51bGwgfHwgdHlwZW9mIHNyYyAhPT0gJ29iamVjdCcpIHJldHVybiBzcmM7XG5cbiAgaWYgKEFycmF5LmlzQXJyYXkoc3JjKSkge1xuICAgIGlmIChzcmMubGVuZ3RoID09PSAwKSByZXR1cm4gW107IC8vIGVtcHR5IHNyYyA9IGNsZWFyLCBub3Qgbm8tb3BcbiAgICBpZiAoQXJyYXkuaXNBcnJheShkc3QpKSByZXR1cm4gWy4uLm5ldyBTZXQoWy4uLmRzdCwgLi4uc3JjXSldO1xuICAgIHJldHVybiBbLi4uc3JjXTtcbiAgfVxuXG4gIGNvbnN0IG91dDogYW55ID0geyAuLi4oZHN0ICYmIHR5cGVvZiBkc3QgPT09ICdvYmplY3QnID8gZHN0IDoge30pIH07XG4gIC8vIE9iamVjdC5rZXlzKCkgaXMgb3duLWVudW1lcmFibGUtb25seSBieSBzcGVjIOKAlCBubyBERU5JRUQgY2hlY2sgbmVlZGVkIGhlcmUuXG4gIGZvciAoY29uc3QgayBvZiBPYmplY3Qua2V5cyhzcmMpKSB7XG4gICAgb3V0W2tdID0gZGVlcFNtYXJ0TWVyZ2Uob3V0W2tdLCBzcmNba10pO1xuICB9XG4gIHJldHVybiBvdXQ7XG59XG5cbi8qKlxuICogQXBwbGllcyBhIGNvbW1pdCBidW5kbGUgdG8gYSBiYXNlIHN0YXRlIGJ5IHJlcGxheWluZyBvcGVyYXRpb25zIGluIG9yZGVyLlxuICogR3VhcmFudGVlcyBcImxhc3Qgd3JpdGVyIHdpbnNcIiBzZW1hbnRpY3MuXG4gKlxuICogVGhlIHNpbmdsZSByZXBsYXkgcHJpbWl0aXZlIOKAlCB0aHJlZSBjb25zdW1lcnMgaW5oZXJpdCBldmVyeSB2ZXJiIGZyb20gaXQ6XG4gKiBsaXZlIHN0YXRlIChgU2hhcmVkTWVtb3J5LmFwcGx5UGF0Y2hgKSwgdGltZSB0cmF2ZWxcbiAqIChgRXZlbnRMb2cubWF0ZXJpYWxpc2VgKSwgYW5kIHRoZSByZWRhY3RlZCBtaXJyb3JcbiAqIChgU3RhZ2VDb250ZXh0LmNvbW1pdGAncyBzZWNvbmQgYGFwcGx5UGF0Y2hgKS5cbiAqXG4gKiBWZXJiIGFybXM6XG4gKiAgIC0gYCdzZXQnYCAgICDigJQgb3ZlcndyaXRlIHdpdGggYG92ZXJ3cml0ZVtwYXRoXWAgKHRoZSBmdWxsIGZpbmFsIHZhbHVlKS5cbiAqICAgLSBgJ21lcmdlJ2AgIOKAlCBgZGVlcFNtYXJ0TWVyZ2VgIHRoZSBhY2N1bXVsYXRlZCBgdXBkYXRlc1twYXRoXWAgZGVsdGEgaW4uXG4gKiAgIC0gYCdhcHBlbmQnYCDigJQgKCMxM2MtQiBkZWx0YSBtb2RlKSBgb3ZlcndyaXRlW3BhdGhdYCBob2xkcyBPTkxZIHRoZSB0YWlsO1xuICogICAgIHJlY29uc3RydWN0IGJ5IGNvbmNhdGVuYXRpbmcgaXQgb250byB0aGUgY3VycmVudCBhcnJheS4gV2hlbiB0aGVcbiAqICAgICBjdXJyZW50IHZhbHVlIG9yIHRoZSByZWNvcmRlZCB0YWlsIGlzIG5vdCBhbiBhcnJheSAob3V0LW9mLW9yZGVyXG4gKiAgICAgcmVwbGF5IGJhc2UsIG9yIGEgUkVEQUNURUQgdGFpbCDigJQgYHJlZGFjdFBhdGNoYCByZXBsYWNlcyBtYXRjaGVkXG4gKiAgICAgcGF5bG9hZHMgd2l0aCB0aGUgYCdSRURBQ1RFRCdgIHN0cmluZyksIGRlZ3JhZGUgdG8gYSBkaXJlY3Qgc2V0IG9mIHRoZVxuICogICAgIHJlY29yZGVkIHZhbHVlIOKAlCB0aGUgc2FtZSB0ZXJtaW5hbCB2YWx1ZSBhIHJlZGFjdGVkL2NvcnJ1cHQgYCdzZXQnYFxuICogICAgIHByb2R1Y2VzLlxuICogICAtIGAnZGVsZXRlJ2Ag4oCUICgjMTNjLUIgZGVsdGEgbW9kZSkgcmVtb3ZlIHRoZSBrZXkgKGBuYXRpdmVEZWxldGVgLFxuICogICAgIHByb3RvdHlwZS1wb2xsdXRpb24tc2FmZSkuIFRoZSBwYXRoIHN0YXlzIGVudW1lcmF0ZWQgaW4gYG92ZXJ3cml0ZWBcbiAqICAgICAodmFsdWUgYHVuZGVmaW5lZGApIGZvciBrZXktc2V0IGNvbnN1bWVyczsgcmVwbGF5IGlnbm9yZXMgdGhhdCB2YWx1ZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5U21hcnRNZXJnZShiYXNlOiBhbnksIHVwZGF0ZXM6IE1lbW9yeVBhdGNoLCBvdmVyd3JpdGU6IE1lbW9yeVBhdGNoLCB0cmFjZTogVHJhY2VFbnRyeVtdKTogYW55IHtcbiAgY29uc3Qgb3V0ID0gc3RydWN0dXJlZENsb25lKGJhc2UpO1xuICBmb3IgKGNvbnN0IHsgcGF0aCwgdmVyYiB9IG9mIHRyYWNlKSB7XG4gICAgY29uc3Qgc2VncyA9IHBhdGguc3BsaXQoREVMSU0pO1xuICAgIGlmICh2ZXJiID09PSAnc2V0Jykge1xuICAgICAgX3NldChvdXQsIHNlZ3MsIHN0cnVjdHVyZWRDbG9uZShfZ2V0KG92ZXJ3cml0ZSwgc2VncykpKTtcbiAgICB9IGVsc2UgaWYgKHZlcmIgPT09ICdhcHBlbmQnKSB7XG4gICAgICBjb25zdCB0YWlsID0gc3RydWN0dXJlZENsb25lKF9nZXQob3ZlcndyaXRlLCBzZWdzKSk7XG4gICAgICBjb25zdCBjdXJyZW50ID0gX2dldChvdXQsIHNlZ3MpO1xuICAgICAgX3NldChvdXQsIHNlZ3MsIEFycmF5LmlzQXJyYXkoY3VycmVudCkgJiYgQXJyYXkuaXNBcnJheSh0YWlsKSA/IFsuLi5jdXJyZW50LCAuLi50YWlsXSA6IHRhaWwpO1xuICAgIH0gZWxzZSBpZiAodmVyYiA9PT0gJ2RlbGV0ZScpIHtcbiAgICAgIG5hdGl2ZURlbGV0ZShvdXQsIHNlZ3MpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBjdXJyZW50ID0gX2dldChvdXQsIHNlZ3MpID8/IHt9O1xuICAgICAgX3NldChvdXQsIHNlZ3MsIGRlZXBTbWFydE1lcmdlKGN1cnJlbnQsIF9nZXQodXBkYXRlcywgc2VncykpKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG91dDtcbn1cbiJdfQ==
|
|
287
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL21lbW9yeS91dGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7R0FLRztBQUVILE9BQU8sRUFBRSxZQUFZLEVBQUUsU0FBUyxJQUFJLElBQUksRUFBRSxTQUFTLElBQUksSUFBSSxFQUFFLFNBQVMsSUFBSSxJQUFJLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFHckcsaUZBQWlGO0FBQ2pGLE1BQU0sQ0FBQyxNQUFNLEtBQUssR0FBRyxRQUFRLENBQUM7QUFJOUI7OztHQUdHO0FBQ0gsTUFBTSxVQUFVLG9CQUFvQixDQUFDLEtBQWMsRUFBRSxPQUE0QixFQUFFO0lBQ2pGLE9BQU87UUFDTCxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUztRQUNyRCxVQUFVLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQztLQUN0QixDQUFDO0FBQ0osQ0FBQztBQUVEOztHQUVHO0FBQ0gsTUFBTSxVQUFVLGNBQWMsQ0FDNUIsR0FBaUIsRUFDakIsS0FBYSxFQUNiLEtBQWUsRUFDZixLQUFhLEVBQ2IsS0FBUSxFQUNSLGFBQXVCO0lBRXZCLE1BQU0sRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLEdBQUcsb0JBQW9CLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ25FLE1BQU0sSUFBSSxHQUFHLE9BQU8sSUFBSSxVQUFVLENBQUM7SUFDbkMsTUFBTSxRQUFRLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQzNCLElBQUksT0FBTyxHQUFpQixHQUFHLENBQUM7SUFDaEMsT0FBTyxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQzNCLE1BQU0sR0FBRyxHQUFHLFFBQVEsQ0FBQyxLQUFLLEVBQVksQ0FBQztRQUN2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QUMsT0FBTyxDQUFDLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLE9BQU8sRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNoRyxDQUFDO2FBQU0sSUFBSSxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDN0IsWUFBWSxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUMxQixDQUFDO2FBQU0sQ0FBQztZQUNOLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ3RDLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLGNBQWMsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDaEUsQ0FBQztJQUNILENBQUM7SUFDRCxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIHV0aWxzLnRzIOKAlCBIZWxwZXIgZnVuY3Rpb25zIGZvciBuZXN0ZWQgb2JqZWN0IG1hbmlwdWxhdGlvblxuICpcbiAqIFByb3ZpZGVzIGNvbnNpc3RlbnQgcGF0aCB0cmF2ZXJzYWwgYW5kIHZhbHVlIG1hbmlwdWxhdGlvbiBmb3IgdGhlIG1lbW9yeSBzeXN0ZW0uXG4gKiBaZXJvIGV4dGVybmFsIGRlcGVuZGVuY2llcy5cbiAqL1xuXG5pbXBvcnQgeyBuYXRpdmVEZWxldGUsIG5hdGl2ZUdldCBhcyBfZ2V0LCBuYXRpdmVIYXMgYXMgX2hhcywgbmF0aXZlU2V0IGFzIF9zZXQgfSBmcm9tICcuL3BhdGhPcHMuanMnO1xuaW1wb3J0IHR5cGUgeyBNZW1vcnlQYXRjaCwgVHJhY2VFbnRyeSB9IGZyb20gJy4vdHlwZXMuanMnO1xuXG4vKiogQVNDSUkgVW5pdC1TZXBhcmF0b3Ig4oCUIGNhbm5vdCBhcHBlYXIgaW4gSlMgaWRlbnRpZmllcnMsIGludmlzaWJsZSBpbiBsb2dzLiAqL1xuZXhwb3J0IGNvbnN0IERFTElNID0gJ1xcdTAwMUYnO1xuXG50eXBlIE5lc3RlZE9iamVjdCA9IHsgW2tleTogc3RyaW5nXTogYW55IH07XG5cbi8qKlxuICogUmVzb2x2ZXMgcnVuLW5hbWVzcGFjZWQgYW5kIGdsb2JhbCBwYXRocy5cbiAqIEVhY2ggZmxvd2NoYXJ0IGV4ZWN1dGlvbiAocnVuKSBzdG9yZXMgZGF0YSB1bmRlciBgcnVucy97aWR9L2AgdG8gcHJldmVudCBjb2xsaXNpb25zLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0UnVuQW5kR2xvYmFsUGF0aHMocnVuSWQ/OiBzdHJpbmcsIHBhdGg6IChzdHJpbmcgfCBudW1iZXIpW10gPSBbXSkge1xuICByZXR1cm4ge1xuICAgIHJ1blBhdGg6IHJ1bklkID8gWydydW5zJywgcnVuSWQsIC4uLnBhdGhdIDogdW5kZWZpbmVkLFxuICAgIGdsb2JhbFBhdGg6IFsuLi5wYXRoXSxcbiAgfTtcbn1cblxuLyoqXG4gKiBTZXRzIGEgdmFsdWUgYXQgYSBuZXN0ZWQgcGF0aCwgY3JlYXRpbmcgaW50ZXJtZWRpYXRlIG9iamVjdHMgYXMgbmVlZGVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0TmVzdGVkVmFsdWU8VD4oXG4gIG9iajogTmVzdGVkT2JqZWN0LFxuICBydW5JZDogc3RyaW5nLFxuICBfcGF0aDogc3RyaW5nW10sXG4gIGZpZWxkOiBzdHJpbmcsXG4gIHZhbHVlOiBULFxuICBkZWZhdWx0VmFsdWVzPzogdW5rbm93bixcbik6IE5lc3RlZE9iamVjdCB7XG4gIGNvbnN0IHsgcnVuUGF0aCwgZ2xvYmFsUGF0aCB9ID0gZ2V0UnVuQW5kR2xvYmFsUGF0aHMocnVuSWQsIF9wYXRoKTtcbiAgY29uc3QgcGF0aCA9IHJ1blBhdGggfHwgZ2xvYmFsUGF0aDtcbiAgY29uc3QgcGF0aENvcHkgPSBbLi4ucGF0aF07XG4gIGxldCBjdXJyZW50OiBOZXN0ZWRPYmplY3QgPSBvYmo7XG4gIHdoaWxlIChwYXRoQ29weS5sZW5ndGggPiAwKSB7XG4gICAgY29uc3Qga2V5ID0gcGF0aENvcHkuc2hpZnQoKSBhcyBzdHJpbmc7XG4gICAgaWYgKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoY3VycmVudCwga2V5KSkge1xuICAgICAgY3VycmVudFtrZXldID0ga2V5ID09PSBydW5JZCAmJiBkZWZhdWx0VmFsdWVzID8gZGVmYXVsdFZhbHVlcyA6IHt9O1xuICAgIH1cbiAgICBjdXJyZW50ID0gY3VycmVudFtrZXldO1xuICB9XG4gIGN1cnJlbnRbZmllbGRdID0gdmFsdWU7XG4gIHJldHVybiBvYmo7XG59XG5cbi8qKlxuICogRGVlcC1tZXJnZXMgYSB2YWx1ZSBpbnRvIHRoZSBvYmplY3QgYXQgdGhlIHNwZWNpZmllZCBwYXRoLlxuICogLSBBcnJheXM6IGNvbmNhdGVuYXRlXG4gKiAtIE9iamVjdHM6IHNoYWxsb3cgbWVyZ2UgYXQgZWFjaCBsZXZlbFxuICogLSBQcmltaXRpdmVzOiByZXBsYWNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1cGRhdGVOZXN0ZWRWYWx1ZTxUPihcbiAgb2JqOiBhbnksXG4gIHJ1bklkOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gIF9wYXRoOiAoc3RyaW5nIHwgbnVtYmVyKVtdLFxuICBmaWVsZDogc3RyaW5nIHwgbnVtYmVyLFxuICB2YWx1ZTogVCxcbiAgZGVmYXVsdFZhbHVlcz86IHVua25vd24sXG4pOiBhbnkge1xuICBjb25zdCB7IHJ1blBhdGgsIGdsb2JhbFBhdGggfSA9IGdldFJ1bkFuZEdsb2JhbFBhdGhzKHJ1bklkLCBfcGF0aCk7XG4gIGNvbnN0IHBhdGggPSBydW5QYXRoIHx8IGdsb2JhbFBhdGg7XG4gIGNvbnN0IHBhdGhDb3B5ID0gWy4uLnBhdGhdO1xuICBsZXQgY3VycmVudDogTmVzdGVkT2JqZWN0ID0gb2JqO1xuICB3aGlsZSAocGF0aENvcHkubGVuZ3RoID4gMCkge1xuICAgIGNvbnN0IGtleSA9IHBhdGhDb3B5LnNoaWZ0KCkgYXMgc3RyaW5nO1xuICAgIGlmICghT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGN1cnJlbnQsIGtleSkpIHtcbiAgICAgIGN1cnJlbnRba2V5XSA9IGtleSA9PT0gcnVuSWQgJiYgZGVmYXVsdFZhbHVlcyA/IGRlZmF1bHRWYWx1ZXMgOiB7fTtcbiAgICB9XG4gICAgY3VycmVudCA9IGN1cnJlbnRba2V5XTtcbiAgfVxuICB1cGRhdGVWYWx1ZShjdXJyZW50LCBmaWVsZCwgdmFsdWUpO1xuICByZXR1cm4gb2JqO1xufVxuXG4vKipcbiAqIEluLXBsYWNlIHZhbHVlIHVwZGF0ZSB3aXRoIG1lcmdlIHNlbWFudGljcy5cbiAqIC0gQXJyYXlzIChub24tZW1wdHkpOiBjb25jYXRlbmF0ZSBvbnRvIGV4aXN0aW5nXG4gKiAtIEFycmF5cyAoZW1wdHkpOiAgICAgZGlyZWN0IHJlcGxhY2Ug4oCUIHdyaXRpbmcgYFtdYCBjbGVhcnMgdGhlIGZpZWxkXG4gKiAtIE9iamVjdHMgKG5vbi1lbXB0eSk6IHNoYWxsb3cgbWVyZ2UgKHNwcmVhZClcbiAqIC0gT2JqZWN0cyAoZW1wdHkpOiAgICBkaXJlY3QgcmVwbGFjZSDigJQgd3JpdGluZyBge31gIGNsZWFycyB0aGUgZmllbGRcbiAqIC0gUHJpbWl0aXZlczogZGlyZWN0IGFzc2lnbm1lbnRcbiAqXG4gKiBOb3RlIG9uIGVtcHR5IGFycmF5czogYm90aCBgdmFsdWUgJiYgQXJyYXkuaXNBcnJheSh2YWx1ZSlgIGFuZFxuICogYEFycmF5LmlzQXJyYXkodmFsdWUpYCBldmFsdWF0ZSB0aGUgc2FtZSBmb3IgYXJyYXlzIOKAlCBgW11gIGlzIHRydXRoeSBpblxuICogSmF2YVNjcmlwdCwgc28gdGhlIGAmJmAgZ3VhcmQgd2FzIG5ldmVyIHRoZSBpc3N1ZS4gVGhlIGFjdHVhbCBidWcgd2FzIHRoZVxuICogY29uY2F0IHBhdGg6IGBbLi4uY3VyLCAuLi5bXV1gIHNpbGVudGx5IHJldHVybmVkIGBjdXJgIHVuY2hhbmdlZCB3aGVuIGB2YWx1ZWBcbiAqIHdhcyBgW11gLCBtYWtpbmcgYHVwZGF0ZVZhbHVlKG9iaiwgJ3RhZ3MnLCBbXSlgIGEgbm8tb3AgaW5zdGVhZCBvZiBhIGNsZWFyLlxuICogVGhlIGZpeCBpcyB0aGUgZXhwbGljaXQgYHZhbHVlLmxlbmd0aCA9PT0gMGAgZWFybHktcmV0dXJuIGJyYW5jaC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZVZhbHVlKG9iamVjdDogYW55LCBrZXk6IHN0cmluZyB8IG51bWJlciwgdmFsdWU6IGFueSk6IHZvaWQge1xuICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICBpZiAodmFsdWUubGVuZ3RoID09PSAwKSB7XG4gICAgICBvYmplY3Rba2V5XSA9IHZhbHVlOyAvLyBjbGVhcjogW10gcmVwbGFjZXMgd2hhdGV2ZXIgd2FzIHRoZXJlXG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGN1ciA9IG9iamVjdFtrZXldIGFzIGFueTtcbiAgICAgIG9iamVjdFtrZXldID0gY3VyID09PSB1bmRlZmluZWQgPyB2YWx1ZSA6IFsuLi5jdXIsIC4uLnZhbHVlXTtcbiAgICB9XG4gIH0gZWxzZSBpZiAodmFsdWUgJiYgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiBPYmplY3Qua2V5cyh2YWx1ZSkubGVuZ3RoKSB7XG4gICAgY29uc3QgY3VyID0gb2JqZWN0W2tleV0gYXMgYW55O1xuICAgIG9iamVjdFtrZXldID0gY3VyID09PSB1bmRlZmluZWQgPyB2YWx1ZSA6IHsgLi4uY3VyLCAuLi52YWx1ZSB9O1xuICB9IGVsc2Uge1xuICAgIG9iamVjdFtrZXldID0gdmFsdWU7XG4gIH1cbn1cblxuLyoqXG4gKiBHZXRzIGEgdmFsdWUgYXQgYSBuZXN0ZWQgcGF0aCB3aXRoIHByb3RvdHlwZS1wb2xsdXRpb24gcHJvdGVjdGlvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldE5lc3RlZFZhbHVlKHJvb3Q6IGFueSwgcGF0aDogKHN0cmluZyB8IG51bWJlcilbXSwgZmllbGQ/OiBzdHJpbmcgfCBudW1iZXIpOiBhbnkge1xuICBjb25zdCBub2RlID0gcGF0aCAmJiBwYXRoLmxlbmd0aCA+IDAgPyBfZ2V0KHJvb3QsIHBhdGgpIDogcm9vdDtcbiAgaWYgKGZpZWxkID09PSB1bmRlZmluZWQgfHwgbm9kZSA9PT0gdW5kZWZpbmVkKSByZXR1cm4gbm9kZTtcbiAgaWYgKG5vZGUgIT09IG51bGwgJiYgdHlwZW9mIG5vZGUgPT09ICdvYmplY3QnICYmIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChub2RlLCBmaWVsZCkpIHtcbiAgICByZXR1cm4gbm9kZVtmaWVsZF07XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBSZWRhY3RzIHNlbnNpdGl2ZSB2YWx1ZXMgaW4gYSBwYXRjaCBmb3IgbG9nZ2luZy9kZWJ1Z2dpbmcuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWRhY3RQYXRjaChwYXRjaDogTWVtb3J5UGF0Y2gsIHJlZGFjdGVkU2V0OiBTZXQ8c3RyaW5nPik6IE1lbW9yeVBhdGNoIHtcbiAgY29uc3Qgb3V0ID0gc3RydWN0dXJlZENsb25lKHBhdGNoKTtcbiAgZm9yIChjb25zdCBmbGF0IG9mIHJlZGFjdGVkU2V0KSB7XG4gICAgY29uc3QgcGF0aEFyciA9IGZsYXQuc3BsaXQoREVMSU0pO1xuICAgIGlmIChfaGFzKG91dCwgcGF0aEFycikpIHtcbiAgICAgIGNvbnN0IGN1cnIgPSBfZ2V0KG91dCwgcGF0aEFycik7XG4gICAgICBpZiAodHlwZW9mIGN1cnIgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIF9zZXQob3V0LCBwYXRoQXJyLCAnUkVEQUNURUQnKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIG91dDtcbn1cblxuLyoqXG4gKiBOb3JtYWxpc2VzIGFuIGFycmF5IHBhdGggaW50byBhIHN0YWJsZSBzdHJpbmcga2V5IHVzaW5nIERFTElNLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbm9ybWFsaXNlUGF0aChwYXRoOiAoc3RyaW5nIHwgbnVtYmVyKVtdKTogc3RyaW5nIHtcbiAgcmV0dXJuIHBhdGgubWFwKFN0cmluZykuam9pbihERUxJTSk7XG59XG5cbi8qKlxuICogU3RydWN0dXJhbCBkZWVwIGVxdWFsaXR5IGZvciBjb21taXR0ZWQtc3RhdGUgdmFsdWVzLlxuICpcbiAqIFVzZWQgYnkge0BsaW5rIFRyYW5zYWN0aW9uQnVmZmVyfSB0byBkZWNpZGUgd2hldGhlciBhIHN0YWdlIGFjdHVhbGx5IENIQU5HRURcbiAqIGEgcGF0aCBvciBtZXJlbHkgcmUtd3JvdGUgLyByZXZlcnRlZCBpdCB0byB0aGUgdmFsdWUgaXQgYWxyZWFkeSBoZWxkIChhXG4gKiBcIm5vLW9wIHdyaXRlXCIpLiBDb21taXR0ZWQgc3RhdGUgaXMgSlNPTi1zaGFwZWQg4oCUIGl0IG11c3Qgc3Vydml2ZVxuICogYHN0cnVjdHVyZWRDbG9uZWAg4oCUIHNvIHRoaXMgb25seSBuZWVkcyB0byBoYW5kbGUgdGhlIHNoYXBlcyB0aGF0IGNhbiByZWFjaCBhXG4gKiBjb21taXQ6IHByaW1pdGl2ZXMsIGFycmF5cywgYW5kIHBsYWluIG9iamVjdHMuXG4gKlxuICogU2VtYW50aWNzOlxuICogICAtIHJlZmVyZW5jZSAvIGlkZW50aWNhbC1wcmltaXRpdmUgc2hvcnQtY2lyY3VpdHMgZmlyc3QgKGNoZWFwIGZhc3QgcGF0aClcbiAqICAgLSBgTmFOYCBlcXVhbHMgYE5hTmAgKHByaW1pdGl2ZSBjb21wYXJlIGZhbGxzIGJhY2sgdG8gYE9iamVjdC5pc2ApXG4gKiAgIC0gYXJyYXlzOiBlcXVhbCBsZW5ndGggQU5EIGRlZXAtZXF1YWwgZWxlbWVudC13aXNlIChvcmRlci1zZW5zaXRpdmUpXG4gKiAgIC0gb2JqZWN0czogaWRlbnRpY2FsIG93bi1rZXkgc2V0IEFORCBkZWVwLWVxdWFsIHBlciBrZXlcbiAqICAgLSBtaXNtYXRjaGVkIGtpbmRzIChhcnJheSB2cyBvYmplY3QsIG9iamVjdCB2cyBudWxsKSDihpIgbm90IGVxdWFsXG4gKlxuICogQ29zdCAmIHNhZmV0eTpcbiAqICAgLSBBbGxvY2F0ZXMgTk9USElORyBidXQgdHJhbnNpZW50IGBPYmplY3Qua2V5c2AgYXJyYXlzIOKAlCBubyBjbG9uZXMuIEl0IGlzXG4gKiAgICAgc3RyaWN0bHkgY2hlYXBlciB0aGFuIHRoZSBgc3RydWN0dXJlZENsb25lYCB0aGUgY29tbWl0IGFscmVhZHkgcGVyZm9ybXMuXG4gKiAgIC0gUHJpbWl0aXZlIGNvbXBhcmlzb25zICh0aGUgYnVsayBvZiBzdGF0ZSkgYXJlIE8oMSkgdmlhIHRoZSBgPT09YCAvXG4gKiAgICAgYE9iamVjdC5pc2AgZmFzdCBwYXRoczsgb25seSBuZXN0ZWQgb2JqZWN0cy9hcnJheXMgaW5jdXIgYSB3YWxrLCBib3VuZGVkXG4gKiAgICAgYnkgdGhlIHZhbHVlJ3Mgb3duIHNpemUuXG4gKiAgIC0gVGVybWluYXRlcyBvbiBDWUNMSUMgdmFsdWVzICg5LjE4LjEpOiBhIHN0YXRlIHZhbHVlIG11c3Qgc3Vydml2ZVxuICogICAgIGBzdHJ1Y3R1cmVkQ2xvbmVgLCBhbmQgYHN0cnVjdHVyZWRDbG9uZWAgcHJlc2VydmVzIGN5Y2xlcyDigJQgc28gYVxuICogICAgIHNlbGYtcmVmZXJlbmNpbmcgdmFsdWUgaXMgYSBsZWdhbCB2YWx1ZSwgbm90IGFuIG91dC1vZi1jb250cmFjdCBvbmUuIEFcbiAqICAgICBwYWlyIG9mIG9iamVjdHMgYWxyZWFkeSB1bmRlciBjb21wYXJpc29uIGlzIHRyZWF0ZWQgYXMgZXF1YWwgKHRoZVxuICogICAgIHN0cnVjdHVyYWwgYW5zd2VyLCBsb2Rhc2ggYGlzRXF1YWxgIHNlbWFudGljcyk7IGFjeWNsaWMgaW5wdXRzIHNlZSBub1xuICogICAgIGNoYW5nZS4gRGV2IG1vZGUgc3RpbGwgd2FybnMgYWJvdXQgY3ljbGVzIGF0IHdyaXRlIHRpbWVcbiAqICAgICAoYFNjb3BlRmFjYWRlLnNldFZhbHVlYCkgYmVjYXVzZSB0aGV5IHN1cnByaXNlIG5hcnJhdGl2ZSBhbmQgSlNPTi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlZXBFcXVhbChhOiBhbnksIGI6IGFueSk6IGJvb2xlYW4ge1xuICByZXR1cm4gZXF1YWxQYWlycyhhLCBiLCB1bmRlZmluZWQpO1xufVxuXG4vKipcbiAqIE9iamVjdCBwYWlycyBtZXQgc28gZmFyLCBrZXllZCBgYSDihpIgdGhlIGIncyBpdCBoYXMgYmVlbiBwYWlyZWQgd2l0aGAuIENyZWF0ZWRcbiAqIGxhemlseSBieSB0aGUgZmlyc3Qgb2JqZWN0IHBhaXIsIHNvIHByaW1pdGl2ZSBjb21wYXJlcyBhbGxvY2F0ZSBub3RoaW5nLlxuICogTmV2ZXIgcHJ1bmVkOiBldmVyeSBgZmFsc2VgIHJldHVybnMgc3RyYWlnaHQgdXAgdG8gdGhlIGNhbGxlciAoZWFjaCByZWN1cnNpdmVcbiAqIGNhbGwgc2hvcnQtY2lyY3VpdHMgb24gaXQpLCBzbyBub3RoaW5nIGlzIGxvb2tlZCB1cCBhZnRlciBhIG1pc21hdGNoIOKAlCBhXG4gKiBzdG9yZWQgcGFpciBpcyBlaXRoZXIgc3RpbGwgdW5kZXIgY29tcGFyaXNvbiBvciBhbHJlYWR5IGtub3duIGVxdWFsLlxuICovXG50eXBlIFNlZW5QYWlycyA9IFdlYWtNYXA8b2JqZWN0LCBXZWFrU2V0PG9iamVjdD4+O1xuXG5mdW5jdGlvbiBlcXVhbFBhaXJzKGE6IGFueSwgYjogYW55LCBzZWVuOiBTZWVuUGFpcnMgfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgaWYgKGEgPT09IGIpIHJldHVybiB0cnVlOyAvLyBzYW1lIHJlZmVyZW5jZSBvciBpZGVudGljYWwgcHJpbWl0aXZlXG4gIGlmICh0eXBlb2YgYSAhPT0gdHlwZW9mIGIpIHJldHVybiBmYWxzZTtcbiAgaWYgKGEgPT09IG51bGwgfHwgYiA9PT0gbnVsbCkgcmV0dXJuIGEgPT09IGI7IC8vIG9uZSBpcyBudWxsLCB0aGUgb3RoZXIgaXNuJ3RcbiAgaWYgKHR5cGVvZiBhICE9PSAnb2JqZWN0JykgcmV0dXJuIE9iamVjdC5pcyhhLCBiKTsgLy8gTmFOLXNhZmUgcHJpbWl0aXZlIGNvbXBhcmVcblxuICBjb25zdCBhSXNBcnJheSA9IEFycmF5LmlzQXJyYXkoYSk7XG4gIGlmIChhSXNBcnJheSAhPT0gQXJyYXkuaXNBcnJheShiKSkgcmV0dXJuIGZhbHNlOyAvLyBhcnJheSB2cyBwbGFpbiBvYmplY3RcblxuICAvLyBDeWNsZSBndWFyZCDigJQgYSBwYWlyIHdlIGFyZSBhbHJlYWR5IGluc2lkZSBpcyBlcXVhbCBieSBhc3N1bXB0aW9uLlxuICBzZWVuID8/PSBuZXcgV2Vha01hcCgpO1xuICBsZXQgcGFydG5lcnMgPSBzZWVuLmdldChhKTtcbiAgaWYgKHBhcnRuZXJzPy5oYXMoYikpIHJldHVybiB0cnVlO1xuICBpZiAoIXBhcnRuZXJzKSBzZWVuLnNldChhLCAocGFydG5lcnMgPSBuZXcgV2Vha1NldCgpKSk7XG4gIHBhcnRuZXJzLmFkZChiKTtcblxuICBpZiAoYUlzQXJyYXkpIHtcbiAgICBpZiAoYS5sZW5ndGggIT09IGIubGVuZ3RoKSByZXR1cm4gZmFsc2U7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoIWVxdWFsUGFpcnMoYVtpXSwgYltpXSwgc2VlbikpIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBjb25zdCBhS2V5cyA9IE9iamVjdC5rZXlzKGEpO1xuICBjb25zdCBiS2V5cyA9IE9iamVjdC5rZXlzKGIpO1xuICBpZiAoYUtleXMubGVuZ3RoICE9PSBiS2V5cy5sZW5ndGgpIHJldHVybiBmYWxzZTtcbiAgZm9yIChjb25zdCBrZXkgb2YgYUtleXMpIHtcbiAgICBpZiAoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBrZXkpKSByZXR1cm4gZmFsc2U7XG4gICAgaWYgKCFlcXVhbFBhaXJzKGFba2V5XSwgYltrZXldLCBzZWVuKSkgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiB0cnVlO1xufVxuXG4vKipcbiAqIERlZXAgdW5pb24gbWVyZ2UgaGVscGVyLlxuICogLSBBcnJheXMgKG5vbi1lbXB0eSk6IHVuaW9uIHdpdGhvdXQgZHVwbGljYXRlcyAoZW5jb3VudGVyIG9yZGVyIHByZXNlcnZlZClcbiAqIC0gQXJyYXlzIChlbXB0eSk6ICAgICByZXBsYWNlIOKAlCBzcmMgYFtdYCBjbGVhcnMgdGhlIGRlc3RpbmF0aW9uIGFycmF5LlxuICogICBSYXRpb25hbGU6IHdyaXRpbmcgYHNjb3BlLnRhZ3MgPSBbXWAgbWVhbnMgXCJjbGVhciB0YWdzXCIsIG5vdCBcImFwcGVuZCBub3RoaW5nXCIuXG4gKiAgIFdpdGhvdXQgdGhpcyBydWxlLCBhbiBlbXB0eS1hcnJheSB3cml0ZSBzaWxlbnRseSBiZWNvbWVzIGEgbm8tb3Agd2hpY2ggaXNcbiAqICAgaW1wb3NzaWJsZSB0byBkaXN0aW5ndWlzaCBmcm9tIGEgYnVnLlxuICogLSBPYmplY3RzOiByZWN1cnNpdmUgbWVyZ2VcbiAqIC0gUHJpbWl0aXZlczogc291cmNlIHdpbnNcbiAqXG4gKiBUZXJtaW5hdGVzIG9uIGEgQ1lDTElDIGBzcmNgICg5LjE4LjEsIHNhbWUgbGF3IGFzIHtAbGluayBkZWVwRXF1YWx9OiBhXG4gKiBzdGF0ZSB2YWx1ZSBzdXJ2aXZlcyBgc3RydWN0dXJlZENsb25lYCwgd2hpY2ggcHJlc2VydmVzIGN5Y2xlcykuIEEgYHNyY2BcbiAqIG9iamVjdCByZS1lbnRlcmVkIHdoaWxlIGl0IGlzIHN0aWxsIGJlaW5nIG1lcmdlZCBoaWdoZXIgdXAgdGhlIHN0YWNrIGhhbmRzXG4gKiBiYWNrIHRoZSBvdXRwdXQgYmVpbmcgYnVpbHQgZm9yIGl0LCBzbyB0aGUgbWVyZ2VkIHZhbHVlIG1pcnJvcnMgdGhlIGN5Y2xlXG4gKiBpbnN0ZWFkIG9mIHVucm9sbGluZyBpdCBmb3JldmVyLiBPbmx5IHRoZSBhbmNlc3RvcnMgb24gdGhlIHN0YWNrIGFyZVxuICogZ3VhcmRlZCDigJQgYSBzaGFyZWQgKGFjeWNsaWMpIGBzcmNgIHJlZmVyZW5jZSBtZXQgYWdhaW4gYXQgYSBkaWZmZXJlbnRcbiAqIGBkc3RgIG1lcmdlcyBhZ2FpbnN0IFRIQVQgYGRzdGAsIGV4YWN0bHkgYXMgYmVmb3JlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVlcFNtYXJ0TWVyZ2UoZHN0OiBhbnksIHNyYzogYW55KTogYW55IHtcbiAgcmV0dXJuIG1lcmdlR3VhcmRlZChkc3QsIHNyYywgdW5kZWZpbmVkKTtcbn1cblxuZnVuY3Rpb24gbWVyZ2VHdWFyZGVkKGRzdDogYW55LCBzcmM6IGFueSwgaW5GbGlnaHQ6IFdlYWtNYXA8b2JqZWN0LCBhbnk+IHwgdW5kZWZpbmVkKTogYW55IHtcbiAgaWYgKHNyYyA9PT0gbnVsbCB8fCB0eXBlb2Ygc3JjICE9PSAnb2JqZWN0JykgcmV0dXJuIHNyYztcblxuICBpZiAoQXJyYXkuaXNBcnJheShzcmMpKSB7XG4gICAgaWYgKHNyYy5sZW5ndGggPT09IDApIHJldHVybiBbXTsgLy8gZW1wdHkgc3JjID0gY2xlYXIsIG5vdCBuby1vcFxuICAgIGlmIChBcnJheS5pc0FycmF5KGRzdCkpIHJldHVybiBbLi4ubmV3IFNldChbLi4uZHN0LCAuLi5zcmNdKV07XG4gICAgcmV0dXJuIFsuLi5zcmNdO1xuICB9XG5cbiAgaWYgKGluRmxpZ2h0Py5oYXMoc3JjKSkgcmV0dXJuIGluRmxpZ2h0LmdldChzcmMpOyAvLyBjeWNsZSDigJQgcmUtZW50ZXIgdGhlIHZhbHVlIGJlaW5nIGJ1aWx0XG5cbiAgY29uc3Qgb3V0OiBhbnkgPSB7IC4uLihkc3QgJiYgdHlwZW9mIGRzdCA9PT0gJ29iamVjdCcgPyBkc3QgOiB7fSkgfTtcbiAgKGluRmxpZ2h0ID8/PSBuZXcgV2Vha01hcCgpKS5zZXQoc3JjLCBvdXQpO1xuICAvLyBPYmplY3Qua2V5cygpIGlzIG93bi1lbnVtZXJhYmxlLW9ubHkgYnkgc3BlYyDigJQgbm8gREVOSUVEIGNoZWNrIG5lZWRlZCBoZXJlLlxuICBmb3IgKGNvbnN0IGsgb2YgT2JqZWN0LmtleXMoc3JjKSkge1xuICAgIG91dFtrXSA9IG1lcmdlR3VhcmRlZChvdXRba10sIHNyY1trXSwgaW5GbGlnaHQpO1xuICB9XG4gIGluRmxpZ2h0LmRlbGV0ZShzcmMpO1xuICByZXR1cm4gb3V0O1xufVxuXG4vKipcbiAqIEFwcGxpZXMgYSBjb21taXQgYnVuZGxlIHRvIGEgYmFzZSBzdGF0ZSBieSByZXBsYXlpbmcgb3BlcmF0aW9ucyBpbiBvcmRlci5cbiAqIEd1YXJhbnRlZXMgXCJsYXN0IHdyaXRlciB3aW5zXCIgc2VtYW50aWNzLlxuICpcbiAqIFRoZSBzaW5nbGUgcmVwbGF5IHByaW1pdGl2ZSDigJQgdGhyZWUgY29uc3VtZXJzIGluaGVyaXQgZXZlcnkgdmVyYiBmcm9tIGl0OlxuICogbGl2ZSBzdGF0ZSAoYFNoYXJlZE1lbW9yeS5hcHBseVBhdGNoYCksIHRpbWUgdHJhdmVsXG4gKiAoYEV2ZW50TG9nLm1hdGVyaWFsaXNlYCksIGFuZCB0aGUgcmVkYWN0ZWQgbWlycm9yXG4gKiAoYFN0YWdlQ29udGV4dC5jb21taXRgJ3Mgc2Vjb25kIGBhcHBseVBhdGNoYCkuXG4gKlxuICogVmVyYiBhcm1zOlxuICogICAtIGAnc2V0J2AgICAg4oCUIG92ZXJ3cml0ZSB3aXRoIGBvdmVyd3JpdGVbcGF0aF1gICh0aGUgZnVsbCBmaW5hbCB2YWx1ZSkuXG4gKiAgIC0gYCdtZXJnZSdgICDigJQgYGRlZXBTbWFydE1lcmdlYCB0aGUgYWNjdW11bGF0ZWQgYHVwZGF0ZXNbcGF0aF1gIGRlbHRhIGluLlxuICogICAtIGAnYXBwZW5kJ2Ag4oCUICgjMTNjLUIgZGVsdGEgbW9kZSkgYG92ZXJ3cml0ZVtwYXRoXWAgaG9sZHMgT05MWSB0aGUgdGFpbDtcbiAqICAgICByZWNvbnN0cnVjdCBieSBjb25jYXRlbmF0aW5nIGl0IG9udG8gdGhlIGN1cnJlbnQgYXJyYXkuIFdoZW4gdGhlXG4gKiAgICAgY3VycmVudCB2YWx1ZSBvciB0aGUgcmVjb3JkZWQgdGFpbCBpcyBub3QgYW4gYXJyYXkgKG91dC1vZi1vcmRlclxuICogICAgIHJlcGxheSBiYXNlLCBvciBhIFJFREFDVEVEIHRhaWwg4oCUIGByZWRhY3RQYXRjaGAgcmVwbGFjZXMgbWF0Y2hlZFxuICogICAgIHBheWxvYWRzIHdpdGggdGhlIGAnUkVEQUNURUQnYCBzdHJpbmcpLCBkZWdyYWRlIHRvIGEgZGlyZWN0IHNldCBvZiB0aGVcbiAqICAgICByZWNvcmRlZCB2YWx1ZSDigJQgdGhlIHNhbWUgdGVybWluYWwgdmFsdWUgYSByZWRhY3RlZC9jb3JydXB0IGAnc2V0J2BcbiAqICAgICBwcm9kdWNlcy5cbiAqICAgLSBgJ2RlbGV0ZSdgIOKAlCAoIzEzYy1CIGRlbHRhIG1vZGUpIHJlbW92ZSB0aGUga2V5IChgbmF0aXZlRGVsZXRlYCxcbiAqICAgICBwcm90b3R5cGUtcG9sbHV0aW9uLXNhZmUpLiBUaGUgcGF0aCBzdGF5cyBlbnVtZXJhdGVkIGluIGBvdmVyd3JpdGVgXG4gKiAgICAgKHZhbHVlIGB1bmRlZmluZWRgKSBmb3Iga2V5LXNldCBjb25zdW1lcnM7IHJlcGxheSBpZ25vcmVzIHRoYXQgdmFsdWUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBseVNtYXJ0TWVyZ2UoYmFzZTogYW55LCB1cGRhdGVzOiBNZW1vcnlQYXRjaCwgb3ZlcndyaXRlOiBNZW1vcnlQYXRjaCwgdHJhY2U6IFRyYWNlRW50cnlbXSk6IGFueSB7XG4gIGNvbnN0IG91dCA9IHN0cnVjdHVyZWRDbG9uZShiYXNlKTtcbiAgZm9yIChjb25zdCB7IHBhdGgsIHZlcmIgfSBvZiB0cmFjZSkge1xuICAgIGNvbnN0IHNlZ3MgPSBwYXRoLnNwbGl0KERFTElNKTtcbiAgICBpZiAodmVyYiA9PT0gJ3NldCcpIHtcbiAgICAgIF9zZXQob3V0LCBzZWdzLCBzdHJ1Y3R1cmVkQ2xvbmUoX2dldChvdmVyd3JpdGUsIHNlZ3MpKSk7XG4gICAgfSBlbHNlIGlmICh2ZXJiID09PSAnYXBwZW5kJykge1xuICAgICAgY29uc3QgdGFpbCA9IHN0cnVjdHVyZWRDbG9uZShfZ2V0KG92ZXJ3cml0ZSwgc2VncykpO1xuICAgICAgY29uc3QgY3VycmVudCA9IF9nZXQob3V0LCBzZWdzKTtcbiAgICAgIF9zZXQob3V0LCBzZWdzLCBBcnJheS5pc0FycmF5KGN1cnJlbnQpICYmIEFycmF5LmlzQXJyYXkodGFpbCkgPyBbLi4uY3VycmVudCwgLi4udGFpbF0gOiB0YWlsKTtcbiAgICB9IGVsc2UgaWYgKHZlcmIgPT09ICdkZWxldGUnKSB7XG4gICAgICBuYXRpdmVEZWxldGUob3V0LCBzZWdzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgY3VycmVudCA9IF9nZXQob3V0LCBzZWdzKSA/PyB7fTtcbiAgICAgIF9zZXQob3V0LCBzZWdzLCBkZWVwU21hcnRNZXJnZShjdXJyZW50LCBfZ2V0KHVwZGF0ZXMsIHNlZ3MpKSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBvdXQ7XG59XG4iXX0=
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* axis.ts — the shape of an axis, and the one safe way to narrow it.
|
|
3
|
+
*
|
|
4
|
+
* WHY THIS FILE EXISTS. `commitStops` returns `Stop[]`, and every strategy
|
|
5
|
+
* that COMPOSES it (keep the stages my domain recognises, drop the rest) rests
|
|
6
|
+
* on a shape the type never stated: `[start, …stages, end]` for a non-empty
|
|
7
|
+
* log, empty for an empty one. Each composer therefore wrote its own runtime
|
|
8
|
+
* guard against its own reading of the contract, plus a mocked-substrate test
|
|
9
|
+
* to prove the guard fires. That is one invariant, discovered three times, and
|
|
10
|
+
* the library that owns the invariant should be the one that states it.
|
|
11
|
+
*
|
|
12
|
+
* {@link splitAxis} states it. {@link filterStops} then does the whole
|
|
13
|
+
* composition — check the shape, keep what the caller keeps, RE-PARTITION the
|
|
14
|
+
* log so the dropped stages' commits are still folded somewhere, and mark the
|
|
15
|
+
* `'start'` bookend as carrying a prologue — because getting the
|
|
16
|
+
* re-partitioning right by hand is the other thing every composer had to
|
|
17
|
+
* rediscover.
|
|
18
|
+
*/
|
|
19
|
+
import type { AxisSplit, Stop } from './types.js';
|
|
20
|
+
/**
|
|
21
|
+
* Split a strategy's stops into `{ start, stages, end }`, or say why it cannot.
|
|
22
|
+
*
|
|
23
|
+
* THE INVARIANT, stated once: for a non-EMPTY log, `commitStops` returns at
|
|
24
|
+
* least the two bookends, `'start'` first and `'end'` last, with one stop per
|
|
25
|
+
* executed stage in execution order between them. For an EMPTY log it returns
|
|
26
|
+
* `[]` — no bookends around nothing, because a cursor with nowhere to stand
|
|
27
|
+
* should say `reason: 'empty'` rather than offer two positions that are the
|
|
28
|
+
* same position.
|
|
29
|
+
*
|
|
30
|
+
* The two refusals are different facts and must not be collapsed: `'empty'`
|
|
31
|
+
* means the run committed nothing, `'not-bookended'` means a strategy broke
|
|
32
|
+
* the contract. A composer that treats them alike reports a broken strategy as
|
|
33
|
+
* an empty run.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* import { commitStops, splitAxis } from 'footprintjs/trace';
|
|
38
|
+
*
|
|
39
|
+
* const axis = splitAxis(commitStops(snapshot.commitLog, snapshot.executionTree));
|
|
40
|
+
* if (axis.ok) {
|
|
41
|
+
* axis.start.commitIdx; // -1 — the fold base
|
|
42
|
+
* axis.stages.map((s) => s.label);
|
|
43
|
+
* axis.end.lastCommitIdx; // the last bundle in the log
|
|
44
|
+
* } else {
|
|
45
|
+
* axis.reason; // 'empty' | 'not-bookended'
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export declare function splitAxis<TMeta = unknown>(stops: readonly Stop<TMeta>[]): AxisSplit<TMeta>;
|
|
50
|
+
/**
|
|
51
|
+
* What {@link filterStops} does with one stop: drop it, keep it, or keep it
|
|
52
|
+
* carrying the strategy's own label and vocabulary.
|
|
53
|
+
*
|
|
54
|
+
* `false` / `null` / `undefined` drop. `true` keeps it unchanged. An object
|
|
55
|
+
* keeps it and overrides `label` and/or sets `meta` — the strategy's own
|
|
56
|
+
* classification, travelling ON the stop instead of being re-derived from
|
|
57
|
+
* `runtimeStageId` at every read.
|
|
58
|
+
*/
|
|
59
|
+
export type StopFilter<TMeta> = boolean | null | undefined | {
|
|
60
|
+
readonly label?: string;
|
|
61
|
+
readonly meta?: TMeta;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Build a FILTERING strategy's axis out of another strategy's stops.
|
|
65
|
+
*
|
|
66
|
+
* The rule, in one sentence: keep the stages `keep` recognises, and give the
|
|
67
|
+
* survivors the log back.
|
|
68
|
+
*
|
|
69
|
+
* **Meta is the decision's, never inherited.** The input may already be a
|
|
70
|
+
* filtered axis carrying another strategy's `meta`; a `true` (or a meta-less
|
|
71
|
+
* object) keeps the stop and DROPS that meta, so a `Stop<TMeta>` never carries
|
|
72
|
+
* a value of some other type under `TMeta`. The bookends carry none either.
|
|
73
|
+
*
|
|
74
|
+
* **The survivors re-partition the log.** A dropped stage's commits still
|
|
75
|
+
* happened, so they fold into the stop that PRECEDES them: every kept stop's
|
|
76
|
+
* `lastCommitIdx` runs to just before the next kept stop begins. Nothing is
|
|
77
|
+
* orphaned and `stateAt(stop)` stays "the state that existed when the next
|
|
78
|
+
* kept stage started".
|
|
79
|
+
*
|
|
80
|
+
* **What that costs `'start'`, said out loud.** The commits before the first
|
|
81
|
+
* survivor have nowhere else to go, so `'start'` absorbs them: its fold is the
|
|
82
|
+
* run's base PLUS that prologue — the state the first stop READ, not the raw
|
|
83
|
+
* base. The returned start therefore carries `prologue: true` whenever it
|
|
84
|
+
* actually absorbed a stage, and a renderer that means "before anything ran"
|
|
85
|
+
* checks `kind === 'start' && !prologue`. That flag is the whole reason this
|
|
86
|
+
* helper exists rather than a `.filter()` call.
|
|
87
|
+
*
|
|
88
|
+
* **A log with nothing kept** yields the two bookends and nothing between
|
|
89
|
+
* them: `'start'` folds the whole log, `'end'` folds the whole log, and
|
|
90
|
+
* `jumpTo` on any stage id refuses with `reason: 'miss'`. An axis with nowhere
|
|
91
|
+
* meaningful to stand — which is the truthful shape for a run this strategy
|
|
92
|
+
* recognises nothing in, and NOT the `[]` that says the log was empty.
|
|
93
|
+
*
|
|
94
|
+
* @throws when `stops` is non-empty but not bookended — see {@link splitAxis}.
|
|
95
|
+
* Only a strategy can cause that; a run cannot, so it is a contract error
|
|
96
|
+
* and not a condition to fold into the data.
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```typescript
|
|
100
|
+
* import { commitStops, filterStops } from 'footprintjs/trace';
|
|
101
|
+
* import type { Stop, TimeTravelStrategy } from 'footprintjs/trace';
|
|
102
|
+
*
|
|
103
|
+
* type Milestone = { kind: 'llm-turn' | 'tool-call'; label: string };
|
|
104
|
+
* declare function milestoneFor(runtimeStageId: string): Milestone | null;
|
|
105
|
+
*
|
|
106
|
+
* const milestoneStops: TimeTravelStrategy<Milestone> = {
|
|
107
|
+
* stopsFor: (log, tree) =>
|
|
108
|
+
* filterStops<Milestone>(commitStops(log, tree), (stop) => {
|
|
109
|
+
* const m = milestoneFor(stop.runtimeStageId);
|
|
110
|
+
* return m ? { label: m.label, meta: m } : null;
|
|
111
|
+
* }),
|
|
112
|
+
* };
|
|
113
|
+
*
|
|
114
|
+
* const cursor = timeTravel(snapshot, { strategy: milestoneStops });
|
|
115
|
+
* cursor.at()?.meta?.kind; // 'llm-turn' — no re-derivation
|
|
116
|
+
* cursor.stops[0].prologue; // true when stages ran before the first turn
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
export declare function filterStops<TMeta = unknown>(stops: readonly Stop<unknown>[], keep: (stop: Stop<unknown>) => StopFilter<TMeta>): Stop<TMeta>[];
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* axis.ts — the shape of an axis, and the one safe way to narrow it.
|
|
3
|
+
*
|
|
4
|
+
* WHY THIS FILE EXISTS. `commitStops` returns `Stop[]`, and every strategy
|
|
5
|
+
* that COMPOSES it (keep the stages my domain recognises, drop the rest) rests
|
|
6
|
+
* on a shape the type never stated: `[start, …stages, end]` for a non-empty
|
|
7
|
+
* log, empty for an empty one. Each composer therefore wrote its own runtime
|
|
8
|
+
* guard against its own reading of the contract, plus a mocked-substrate test
|
|
9
|
+
* to prove the guard fires. That is one invariant, discovered three times, and
|
|
10
|
+
* the library that owns the invariant should be the one that states it.
|
|
11
|
+
*
|
|
12
|
+
* {@link splitAxis} states it. {@link filterStops} then does the whole
|
|
13
|
+
* composition — check the shape, keep what the caller keeps, RE-PARTITION the
|
|
14
|
+
* log so the dropped stages' commits are still folded somewhere, and mark the
|
|
15
|
+
* `'start'` bookend as carrying a prologue — because getting the
|
|
16
|
+
* re-partitioning right by hand is the other thing every composer had to
|
|
17
|
+
* rediscover.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Split a strategy's stops into `{ start, stages, end }`, or say why it cannot.
|
|
21
|
+
*
|
|
22
|
+
* THE INVARIANT, stated once: for a non-EMPTY log, `commitStops` returns at
|
|
23
|
+
* least the two bookends, `'start'` first and `'end'` last, with one stop per
|
|
24
|
+
* executed stage in execution order between them. For an EMPTY log it returns
|
|
25
|
+
* `[]` — no bookends around nothing, because a cursor with nowhere to stand
|
|
26
|
+
* should say `reason: 'empty'` rather than offer two positions that are the
|
|
27
|
+
* same position.
|
|
28
|
+
*
|
|
29
|
+
* The two refusals are different facts and must not be collapsed: `'empty'`
|
|
30
|
+
* means the run committed nothing, `'not-bookended'` means a strategy broke
|
|
31
|
+
* the contract. A composer that treats them alike reports a broken strategy as
|
|
32
|
+
* an empty run.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* import { commitStops, splitAxis } from 'footprintjs/trace';
|
|
37
|
+
*
|
|
38
|
+
* const axis = splitAxis(commitStops(snapshot.commitLog, snapshot.executionTree));
|
|
39
|
+
* if (axis.ok) {
|
|
40
|
+
* axis.start.commitIdx; // -1 — the fold base
|
|
41
|
+
* axis.stages.map((s) => s.label);
|
|
42
|
+
* axis.end.lastCommitIdx; // the last bundle in the log
|
|
43
|
+
* } else {
|
|
44
|
+
* axis.reason; // 'empty' | 'not-bookended'
|
|
45
|
+
* }
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export function splitAxis(stops) {
|
|
49
|
+
const kinds = Object.freeze(stops.map((stop) => stop.kind));
|
|
50
|
+
if (stops.length === 0)
|
|
51
|
+
return { ok: false, reason: 'empty', kinds };
|
|
52
|
+
const start = stops[0];
|
|
53
|
+
const end = stops[stops.length - 1];
|
|
54
|
+
if (start.kind !== 'start' || end.kind !== 'end' || stops.length < 2) {
|
|
55
|
+
return { ok: false, reason: 'not-bookended', kinds };
|
|
56
|
+
}
|
|
57
|
+
return { ok: true, start, stages: Object.freeze(stops.slice(1, -1)), end };
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* `stop` retyped to the OUTPUT vocabulary, with any meta it already carried
|
|
61
|
+
* left behind. The input axis may itself be a filtered one (a Beat axis being
|
|
62
|
+
* narrowed into a Tag axis), and a `true` decision keeps the STOP, not the
|
|
63
|
+
* other strategy's classification: a `Stop<Tag>` whose `meta` is a Beat would
|
|
64
|
+
* be a lie the type could not catch. Only the decision may supply a meta.
|
|
65
|
+
*/
|
|
66
|
+
function retyped(stop) {
|
|
67
|
+
if (stop.meta === undefined)
|
|
68
|
+
return stop;
|
|
69
|
+
const out = {};
|
|
70
|
+
const fields = stop;
|
|
71
|
+
for (const key of Object.keys(fields))
|
|
72
|
+
if (key !== 'meta')
|
|
73
|
+
out[key] = fields[key];
|
|
74
|
+
return out;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Build a FILTERING strategy's axis out of another strategy's stops.
|
|
78
|
+
*
|
|
79
|
+
* The rule, in one sentence: keep the stages `keep` recognises, and give the
|
|
80
|
+
* survivors the log back.
|
|
81
|
+
*
|
|
82
|
+
* **Meta is the decision's, never inherited.** The input may already be a
|
|
83
|
+
* filtered axis carrying another strategy's `meta`; a `true` (or a meta-less
|
|
84
|
+
* object) keeps the stop and DROPS that meta, so a `Stop<TMeta>` never carries
|
|
85
|
+
* a value of some other type under `TMeta`. The bookends carry none either.
|
|
86
|
+
*
|
|
87
|
+
* **The survivors re-partition the log.** A dropped stage's commits still
|
|
88
|
+
* happened, so they fold into the stop that PRECEDES them: every kept stop's
|
|
89
|
+
* `lastCommitIdx` runs to just before the next kept stop begins. Nothing is
|
|
90
|
+
* orphaned and `stateAt(stop)` stays "the state that existed when the next
|
|
91
|
+
* kept stage started".
|
|
92
|
+
*
|
|
93
|
+
* **What that costs `'start'`, said out loud.** The commits before the first
|
|
94
|
+
* survivor have nowhere else to go, so `'start'` absorbs them: its fold is the
|
|
95
|
+
* run's base PLUS that prologue — the state the first stop READ, not the raw
|
|
96
|
+
* base. The returned start therefore carries `prologue: true` whenever it
|
|
97
|
+
* actually absorbed a stage, and a renderer that means "before anything ran"
|
|
98
|
+
* checks `kind === 'start' && !prologue`. That flag is the whole reason this
|
|
99
|
+
* helper exists rather than a `.filter()` call.
|
|
100
|
+
*
|
|
101
|
+
* **A log with nothing kept** yields the two bookends and nothing between
|
|
102
|
+
* them: `'start'` folds the whole log, `'end'` folds the whole log, and
|
|
103
|
+
* `jumpTo` on any stage id refuses with `reason: 'miss'`. An axis with nowhere
|
|
104
|
+
* meaningful to stand — which is the truthful shape for a run this strategy
|
|
105
|
+
* recognises nothing in, and NOT the `[]` that says the log was empty.
|
|
106
|
+
*
|
|
107
|
+
* @throws when `stops` is non-empty but not bookended — see {@link splitAxis}.
|
|
108
|
+
* Only a strategy can cause that; a run cannot, so it is a contract error
|
|
109
|
+
* and not a condition to fold into the data.
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* ```typescript
|
|
113
|
+
* import { commitStops, filterStops } from 'footprintjs/trace';
|
|
114
|
+
* import type { Stop, TimeTravelStrategy } from 'footprintjs/trace';
|
|
115
|
+
*
|
|
116
|
+
* type Milestone = { kind: 'llm-turn' | 'tool-call'; label: string };
|
|
117
|
+
* declare function milestoneFor(runtimeStageId: string): Milestone | null;
|
|
118
|
+
*
|
|
119
|
+
* const milestoneStops: TimeTravelStrategy<Milestone> = {
|
|
120
|
+
* stopsFor: (log, tree) =>
|
|
121
|
+
* filterStops<Milestone>(commitStops(log, tree), (stop) => {
|
|
122
|
+
* const m = milestoneFor(stop.runtimeStageId);
|
|
123
|
+
* return m ? { label: m.label, meta: m } : null;
|
|
124
|
+
* }),
|
|
125
|
+
* };
|
|
126
|
+
*
|
|
127
|
+
* const cursor = timeTravel(snapshot, { strategy: milestoneStops });
|
|
128
|
+
* cursor.at()?.meta?.kind; // 'llm-turn' — no re-derivation
|
|
129
|
+
* cursor.stops[0].prologue; // true when stages ran before the first turn
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
export function filterStops(stops, keep) {
|
|
133
|
+
const axis = splitAxis(stops);
|
|
134
|
+
if (!axis.ok) {
|
|
135
|
+
if (axis.reason === 'empty')
|
|
136
|
+
return [];
|
|
137
|
+
throw new Error('filterStops: expected a bookended axis — [start, …stages, end] — got kinds ' +
|
|
138
|
+
`[${axis.kinds.join(', ')}]. Only a strategy can produce that shape; a run cannot.`);
|
|
139
|
+
}
|
|
140
|
+
const kept = [];
|
|
141
|
+
for (const stop of axis.stages) {
|
|
142
|
+
const decision = keep(stop);
|
|
143
|
+
if (!decision)
|
|
144
|
+
continue;
|
|
145
|
+
if (decision === true)
|
|
146
|
+
kept.push({ stop });
|
|
147
|
+
else
|
|
148
|
+
kept.push({ stop, label: decision.label, meta: decision.meta });
|
|
149
|
+
}
|
|
150
|
+
// The log's last index, taken from the `'end'` bookend rather than a length:
|
|
151
|
+
// `end` is the one stop guaranteed to fold the whole log, and this function
|
|
152
|
+
// is never handed the log itself.
|
|
153
|
+
const lastIdx = axis.end.lastCommitIdx;
|
|
154
|
+
const first = kept[0];
|
|
155
|
+
const out = [
|
|
156
|
+
{
|
|
157
|
+
...retyped(axis.start),
|
|
158
|
+
step: 0,
|
|
159
|
+
lastCommitIdx: first ? first.stop.commitIdx - 1 : lastIdx,
|
|
160
|
+
// Only when a STAGE was actually absorbed. An axis that kept everything
|
|
161
|
+
// has the same start it always had, and says nothing it need not say.
|
|
162
|
+
...(first && first.stop.step > 1 ? { prologue: true } : {}),
|
|
163
|
+
...(!first && axis.stages.length > 0 ? { prologue: true } : {}),
|
|
164
|
+
},
|
|
165
|
+
];
|
|
166
|
+
for (const [i, row] of kept.entries()) {
|
|
167
|
+
const next = kept[i + 1];
|
|
168
|
+
out.push({
|
|
169
|
+
...retyped(row.stop),
|
|
170
|
+
step: out.length,
|
|
171
|
+
lastCommitIdx: next ? next.stop.commitIdx - 1 : lastIdx,
|
|
172
|
+
...(row.label !== undefined ? { label: row.label } : {}),
|
|
173
|
+
...(row.meta !== undefined ? { meta: row.meta } : {}),
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
out.push({ ...retyped(axis.end), step: out.length });
|
|
177
|
+
return out;
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXhpcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvdGltZS10cmF2ZWwvYXhpcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FpQkc7QUFJSDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTRCRztBQUNILE1BQU0sVUFBVSxTQUFTLENBQWtCLEtBQTZCO0lBQ3RFLE1BQU0sS0FBSyxHQUF3QixNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ2pGLElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxDQUFDO1FBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsQ0FBQztJQUNyRSxNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdkIsTUFBTSxHQUFHLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDcEMsSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLE9BQU8sSUFBSSxHQUFHLENBQUMsSUFBSSxLQUFLLEtBQUssSUFBSSxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQ3JFLE9BQU8sRUFBRSxFQUFFLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxlQUFlLEVBQUUsS0FBSyxFQUFFLENBQUM7SUFDdkQsQ0FBQztJQUNELE9BQU8sRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUM7QUFDN0UsQ0FBQztB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LEdBQUcsQ0FBQyxJQUFJLENBQUM7WUFDUCxHQUFHLE9BQU8sQ0FBUSxHQUFHLENBQUMsSUFBSSxDQUFDO1lBQzNCLElBQUksRUFBRSxHQUFHLENBQUMsTUFBTTtZQUNoQixhQUFhLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU87WUFDdkQsR0FBRyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxHQUFHLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUN4RCxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUksS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1NBQ3RELENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxPQUFPLENBQVEsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLElBQUksRUFBRSxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztJQUM1RCxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIGF4aXMudHMg4oCUIHRoZSBzaGFwZSBvZiBhbiBheGlzLCBhbmQgdGhlIG9uZSBzYWZlIHdheSB0byBuYXJyb3cgaXQuXG4gKlxuICogV0hZIFRISVMgRklMRSBFWElTVFMuIGBjb21taXRTdG9wc2AgcmV0dXJucyBgU3RvcFtdYCwgYW5kIGV2ZXJ5IHN0cmF0ZWd5XG4gKiB0aGF0IENPTVBPU0VTIGl0IChrZWVwIHRoZSBzdGFnZXMgbXkgZG9tYWluIHJlY29nbmlzZXMsIGRyb3AgdGhlIHJlc3QpIHJlc3RzXG4gKiBvbiBhIHNoYXBlIHRoZSB0eXBlIG5ldmVyIHN0YXRlZDogYFtzdGFydCwg4oCmc3RhZ2VzLCBlbmRdYCBmb3IgYSBub24tZW1wdHlcbiAqIGxvZywgZW1wdHkgZm9yIGFuIGVtcHR5IG9uZS4gRWFjaCBjb21wb3NlciB0aGVyZWZvcmUgd3JvdGUgaXRzIG93biBydW50aW1lXG4gKiBndWFyZCBhZ2FpbnN0IGl0cyBvd24gcmVhZGluZyBvZiB0aGUgY29udHJhY3QsIHBsdXMgYSBtb2NrZWQtc3Vic3RyYXRlIHRlc3RcbiAqIHRvIHByb3ZlIHRoZSBndWFyZCBmaXJlcy4gVGhhdCBpcyBvbmUgaW52YXJpYW50LCBkaXNjb3ZlcmVkIHRocmVlIHRpbWVzLCBhbmRcbiAqIHRoZSBsaWJyYXJ5IHRoYXQgb3ducyB0aGUgaW52YXJpYW50IHNob3VsZCBiZSB0aGUgb25lIHRoYXQgc3RhdGVzIGl0LlxuICpcbiAqIHtAbGluayBzcGxpdEF4aXN9IHN0YXRlcyBpdC4ge0BsaW5rIGZpbHRlclN0b3BzfSB0aGVuIGRvZXMgdGhlIHdob2xlXG4gKiBjb21wb3NpdGlvbiDigJQgY2hlY2sgdGhlIHNoYXBlLCBrZWVwIHdoYXQgdGhlIGNhbGxlciBrZWVwcywgUkUtUEFSVElUSU9OIHRoZVxuICogbG9nIHNvIHRoZSBkcm9wcGVkIHN0YWdlcycgY29tbWl0cyBhcmUgc3RpbGwgZm9sZGVkIHNvbWV3aGVyZSwgYW5kIG1hcmsgdGhlXG4gKiBgJ3N0YXJ0J2AgYm9va2VuZCBhcyBjYXJyeWluZyBhIHByb2xvZ3VlIOKAlCBiZWNhdXNlIGdldHRpbmcgdGhlXG4gKiByZS1wYXJ0aXRpb25pbmcgcmlnaHQgYnkgaGFuZCBpcyB0aGUgb3RoZXIgdGhpbmcgZXZlcnkgY29tcG9zZXIgaGFkIHRvXG4gKiByZWRpc2NvdmVyLlxuICovXG5cbmltcG9ydCB0eXBlIHsgQXhpc1NwbGl0LCBTdG9wLCBTdG9wS2luZCB9IGZyb20gJy4vdHlwZXMuanMnO1xuXG4vKipcbiAqIFNwbGl0IGEgc3RyYXRlZ3kncyBzdG9wcyBpbnRvIGB7IHN0YXJ0LCBzdGFnZXMsIGVuZCB9YCwgb3Igc2F5IHdoeSBpdCBjYW5ub3QuXG4gKlxuICogVEhFIElOVkFSSUFOVCwgc3RhdGVkIG9uY2U6IGZvciBhIG5vbi1FTVBUWSBsb2csIGBjb21taXRTdG9wc2AgcmV0dXJucyBhdFxuICogbGVhc3QgdGhlIHR3byBib29rZW5kcywgYCdzdGFydCdgIGZpcnN0IGFuZCBgJ2VuZCdgIGxhc3QsIHdpdGggb25lIHN0b3AgcGVyXG4gKiBleGVjdXRlZCBzdGFnZSBpbiBleGVjdXRpb24gb3JkZXIgYmV0d2VlbiB0aGVtLiBGb3IgYW4gRU1QVFkgbG9nIGl0IHJldHVybnNcbiAqIGBbXWAg4oCUIG5vIGJvb2tlbmRzIGFyb3VuZCBub3RoaW5nLCBiZWNhdXNlIGEgY3Vyc29yIHdpdGggbm93aGVyZSB0byBzdGFuZFxuICogc2hvdWxkIHNheSBgcmVhc29uOiAnZW1wdHknYCByYXRoZXIgdGhhbiBvZmZlciB0d28gcG9zaXRpb25zIHRoYXQgYXJlIHRoZVxuICogc2FtZSBwb3NpdGlvbi5cbiAqXG4gKiBUaGUgdHdvIHJlZnVzYWxzIGFyZSBkaWZmZXJlbnQgZmFjdHMgYW5kIG11c3Qgbm90IGJlIGNvbGxhcHNlZDogYCdlbXB0eSdgXG4gKiBtZWFucyB0aGUgcnVuIGNvbW1pdHRlZCBub3RoaW5nLCBgJ25vdC1ib29rZW5kZWQnYCBtZWFucyBhIHN0cmF0ZWd5IGJyb2tlXG4gKiB0aGUgY29udHJhY3QuIEEgY29tcG9zZXIgdGhhdCB0cmVhdHMgdGhlbSBhbGlrZSByZXBvcnRzIGEgYnJva2VuIHN0cmF0ZWd5IGFzXG4gKiBhbiBlbXB0eSBydW4uXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGltcG9ydCB7IGNvbW1pdFN0b3BzLCBzcGxpdEF4aXMgfSBmcm9tICdmb290cHJpbnRqcy90cmFjZSc7XG4gKlxuICogY29uc3QgYXhpcyA9IHNwbGl0QXhpcyhjb21taXRTdG9wcyhzbmFwc2hvdC5jb21taXRMb2csIHNuYXBzaG90LmV4ZWN1dGlvblRyZWUpKTtcbiAqIGlmIChheGlzLm9rKSB7XG4gKiAgIGF4aXMuc3RhcnQuY29tbWl0SWR4OyAgICAgICAgICAvLyAtMSDigJQgdGhlIGZvbGQgYmFzZVxuICogICBheGlzLnN0YWdlcy5tYXAoKHMpID0+IHMubGFiZWwpO1xuICogICBheGlzLmVuZC5sYXN0Q29tbWl0SWR4OyAgICAgICAgLy8gdGhlIGxhc3QgYnVuZGxlIGluIHRoZSBsb2dcbiAqIH0gZWxzZSB7XG4gKiAgIGF4aXMucmVhc29uOyAgICAgICAgICAgICAgICAgICAvLyAnZW1wdHknIHwgJ25vdC1ib29rZW5kZWQnXG4gKiB9XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNwbGl0QXhpczxUTWV0YSA9IHVua25vd24+KHN0b3BzOiByZWFkb25seSBTdG9wPFRNZXRhPltdKTogQXhpc1NwbGl0PFRNZXRhPiB7XG4gIGNvbnN0IGtpbmRzOiByZWFkb25seSBTdG9wS2luZFtdID0gT2JqZWN0LmZyZWV6ZShzdG9wcy5tYXAoKHN0b3ApID0+IHN0b3Aua2luZCkpO1xuICBpZiAoc3RvcHMubGVuZ3RoID09PSAwKSByZXR1cm4geyBvazogZmFsc2UsIHJlYXNvbjogJ2VtcHR5Jywga2luZHMgfTtcbiAgY29uc3Qgc3RhcnQgPSBzdG9wc1swXTtcbiAgY29uc3QgZW5kID0gc3RvcHNbc3RvcHMubGVuZ3RoIC0gMV07XG4gIGlmIChzdGFydC5raW5kICE9PSAnc3RhcnQnIHx8IGVuZC5raW5kICE9PSAnZW5kJyB8fCBzdG9wcy5sZW5ndGggPCAyKSB7XG4gICAgcmV0dXJuIHsgb2s6IGZhbHNlLCByZWFzb246ICdub3QtYm9va2VuZGVkJywga2luZHMgfTtcbiAgfVxuICByZXR1cm4geyBvazogdHJ1ZSwgc3RhcnQsIHN0YWdlczogT2JqZWN0LmZyZWV6ZShzdG9wcy5zbGljZSgxLCAtMSkpLCBlbmQgfTtcbn1cblxuLyoqXG4gKiBXaGF0IHtAbGluayBmaWx0ZXJTdG9wc30gZG9lcyB3aXRoIG9uZSBzdG9wOiBkcm9wIGl0LCBrZWVwIGl0LCBvciBrZWVwIGl0XG4gKiBjYXJyeWluZyB0aGUgc3RyYXRlZ3kncyBvd24gbGFiZWwgYW5kIHZvY2FidWxhcnkuXG4gKlxuICogYGZhbHNlYCAvIGBudWxsYCAvIGB1bmRlZmluZWRgIGRyb3AuIGB0cnVlYCBrZWVwcyBpdCB1bmNoYW5nZWQuIEFuIG9iamVjdFxuICoga2VlcHMgaXQgYW5kIG92ZXJyaWRlcyBgbGFiZWxgIGFuZC9vciBzZXRzIGBtZXRhYCDigJQgdGhlIHN0cmF0ZWd5J3Mgb3duXG4gKiBjbGFzc2lmaWNhdGlvbiwgdHJhdmVsbGluZyBPTiB0aGUgc3RvcCBpbnN0ZWFkIG9mIGJlaW5nIHJlLWRlcml2ZWQgZnJvbVxuICogYHJ1bnRpbWVTdGFnZUlkYCBhdCBldmVyeSByZWFkLlxuICovXG5leHBvcnQgdHlwZSBTdG9wRmlsdGVyPFRNZXRhPiA9IGJvb2xlYW4gfCBudWxsIHwgdW5kZWZpbmVkIHwgeyByZWFkb25seSBsYWJlbD86IHN0cmluZzsgcmVhZG9ubHkgbWV0YT86IFRNZXRhIH07XG5cbi8qKlxuICogYHN0b3BgIHJldHlwZWQgdG8gdGhlIE9VVFBVVCB2b2NhYnVsYXJ5LCB3aXRoIGFueSBtZXRhIGl0IGFscmVhZHkgY2FycmllZFxuICogbGVmdCBiZWhpbmQuIFRoZSBpbnB1dCBheGlzIG1heSBpdHNlbGYgYmUgYSBmaWx0ZXJlZCBvbmUgKGEgQmVhdCBheGlzIGJlaW5nXG4gKiBuYXJyb3dlZCBpbnRvIGEgVGFnIGF4aXMpLCBhbmQgYSBgdHJ1ZWAgZGVjaXNpb24ga2VlcHMgdGhlIFNUT1AsIG5vdCB0aGVcbiAqIG90aGVyIHN0cmF0ZWd5J3MgY2xhc3NpZmljYXRpb246IGEgYFN0b3A8VGFnPmAgd2hvc2UgYG1ldGFgIGlzIGEgQmVhdCB3b3VsZFxuICogYmUgYSBsaWUgdGhlIHR5cGUgY291bGQgbm90IGNhdGNoLiBPbmx5IHRoZSBkZWNpc2lvbiBtYXkgc3VwcGx5IGEgbWV0YS5cbiAqL1xuZnVuY3Rpb24gcmV0eXBlZDxUTWV0YT4oc3RvcDogU3RvcDx1bmtub3duPik6IFN0b3A8VE1ldGE+IHtcbiAgaWYgKHN0b3AubWV0YSA9PT0gdW5kZWZpbmVkKSByZXR1cm4gc3RvcCBhcyBTdG9wPFRNZXRhPjtcbiAgY29uc3Qgb3V0OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHt9O1xuICBjb25zdCBmaWVsZHMgPSBzdG9wIGFzIHVua25vd24gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKGZpZWxkcykpIGlmIChrZXkgIT09ICdtZXRhJykgb3V0W2tleV0gPSBmaWVsZHNba2V5XTtcbiAgcmV0dXJuIG91dCBhcyB1bmtub3duIGFzIFN0b3A8VE1ldGE+O1xufVxuXG4vKipcbiAqIEJ1aWxkIGEgRklMVEVSSU5HIHN0cmF0ZWd5J3MgYXhpcyBvdXQgb2YgYW5vdGhlciBzdHJhdGVneSdzIHN0b3BzLlxuICpcbiAqIFRoZSBydWxlLCBpbiBvbmUgc2VudGVuY2U6IGtlZXAgdGhlIHN0YWdlcyBga2VlcGAgcmVjb2duaXNlcywgYW5kIGdpdmUgdGhlXG4gKiBzdXJ2aXZvcnMgdGhlIGxvZyBiYWNrLlxuICpcbiAqICoqTWV0YSBpcyB0aGUgZGVjaXNpb24ncywgbmV2ZXIgaW5oZXJpdGVkLioqIFRoZSBpbnB1dCBtYXkgYWxyZWFkeSBiZSBhXG4gKiBmaWx0ZXJlZCBheGlzIGNhcnJ5aW5nIGFub3RoZXIgc3RyYXRlZ3kncyBgbWV0YWA7IGEgYHRydWVgIChvciBhIG1ldGEtbGVzc1xuICogb2JqZWN0KSBrZWVwcyB0aGUgc3RvcCBhbmQgRFJPUFMgdGhhdCBtZXRhLCBzbyBhIGBTdG9wPFRNZXRhPmAgbmV2ZXIgY2Fycmllc1xuICogYSB2YWx1ZSBvZiBzb21lIG90aGVyIHR5cGUgdW5kZXIgYFRNZXRhYC4gVGhlIGJvb2tlbmRzIGNhcnJ5IG5vbmUgZWl0aGVyLlxuICpcbiAqICoqVGhlIHN1cnZpdm9ycyByZS1wYXJ0aXRpb24gdGhlIGxvZy4qKiBBIGRyb3BwZWQgc3RhZ2UncyBjb21taXRzIHN0aWxsXG4gKiBoYXBwZW5lZCwgc28gdGhleSBmb2xkIGludG8gdGhlIHN0b3AgdGhhdCBQUkVDRURFUyB0aGVtOiBldmVyeSBrZXB0IHN0b3Anc1xuICogYGxhc3RDb21taXRJZHhgIHJ1bnMgdG8ganVzdCBiZWZvcmUgdGhlIG5leHQga2VwdCBzdG9wIGJlZ2lucy4gTm90aGluZyBpc1xuICogb3JwaGFuZWQgYW5kIGBzdGF0ZUF0KHN0b3ApYCBzdGF5cyBcInRoZSBzdGF0ZSB0aGF0IGV4aXN0ZWQgd2hlbiB0aGUgbmV4dFxuICoga2VwdCBzdGFnZSBzdGFydGVkXCIuXG4gKlxuICogKipXaGF0IHRoYXQgY29zdHMgYCdzdGFydCdgLCBzYWlkIG91dCBsb3VkLioqIFRoZSBjb21taXRzIGJlZm9yZSB0aGUgZmlyc3RcbiAqIHN1cnZpdm9yIGhhdmUgbm93aGVyZSBlbHNlIHRvIGdvLCBzbyBgJ3N0YXJ0J2AgYWJzb3JicyB0aGVtOiBpdHMgZm9sZCBpcyB0aGVcbiAqIHJ1bidzIGJhc2UgUExVUyB0aGF0IHByb2xvZ3VlIOKAlCB0aGUgc3RhdGUgdGhlIGZpcnN0IHN0b3AgUkVBRCwgbm90IHRoZSByYXdcbiAqIGJhc2UuIFRoZSByZXR1cm5lZCBzdGFydCB0aGVyZWZvcmUgY2FycmllcyBgcHJvbG9ndWU6IHRydWVgIHdoZW5ldmVyIGl0XG4gKiBhY3R1YWxseSBhYnNvcmJlZCBhIHN0YWdlLCBhbmQgYSByZW5kZXJlciB0aGF0IG1lYW5zIFwiYmVmb3JlIGFueXRoaW5nIHJhblwiXG4gKiBjaGVja3MgYGtpbmQgPT09ICdzdGFydCcgJiYgIXByb2xvZ3VlYC4gVGhhdCBmbGFnIGlzIHRoZSB3aG9sZSByZWFzb24gdGhpc1xuICogaGVscGVyIGV4aXN0cyByYXRoZXIgdGhhbiBhIGAuZmlsdGVyKClgIGNhbGwuXG4gKlxuICogKipBIGxvZyB3aXRoIG5vdGhpbmcga2VwdCoqIHlpZWxkcyB0aGUgdHdvIGJvb2tlbmRzIGFuZCBub3RoaW5nIGJldHdlZW5cbiAqIHRoZW06IGAnc3RhcnQnYCBmb2xkcyB0aGUgd2hvbGUgbG9nLCBgJ2VuZCdgIGZvbGRzIHRoZSB3aG9sZSBsb2csIGFuZFxuICogYGp1bXBUb2Agb24gYW55IHN0YWdlIGlkIHJlZnVzZXMgd2l0aCBgcmVhc29uOiAnbWlzcydgLiBBbiBheGlzIHdpdGggbm93aGVyZVxuICogbWVhbmluZ2Z1bCB0byBzdGFuZCDigJQgd2hpY2ggaXMgdGhlIHRydXRoZnVsIHNoYXBlIGZvciBhIHJ1biB0aGlzIHN0cmF0ZWd5XG4gKiByZWNvZ25pc2VzIG5vdGhpbmcgaW4sIGFuZCBOT1QgdGhlIGBbXWAgdGhhdCBzYXlzIHRoZSBsb2cgd2FzIGVtcHR5LlxuICpcbiAqIEB0aHJvd3Mgd2hlbiBgc3RvcHNgIGlzIG5vbi1lbXB0eSBidXQgbm90IGJvb2tlbmRlZCDigJQgc2VlIHtAbGluayBzcGxpdEF4aXN9LlxuICogICBPbmx5IGEgc3RyYXRlZ3kgY2FuIGNhdXNlIHRoYXQ7IGEgcnVuIGNhbm5vdCwgc28gaXQgaXMgYSBjb250cmFjdCBlcnJvclxuICogICBhbmQgbm90IGEgY29uZGl0aW9uIHRvIGZvbGQgaW50byB0aGUgZGF0YS5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgY29tbWl0U3RvcHMsIGZpbHRlclN0b3BzIH0gZnJvbSAnZm9vdHByaW50anMvdHJhY2UnO1xuICogaW1wb3J0IHR5cGUgeyBTdG9wLCBUaW1lVHJhdmVsU3RyYXRlZ3kgfSBmcm9tICdmb290cHJpbnRqcy90cmFjZSc7XG4gKlxuICogdHlwZSBNaWxlc3RvbmUgPSB7IGtpbmQ6ICdsbG0tdHVybicgfCAndG9vbC1jYWxsJzsgbGFiZWw6IHN0cmluZyB9O1xuICogZGVjbGFyZSBmdW5jdGlvbiBtaWxlc3RvbmVGb3IocnVudGltZVN0YWdlSWQ6IHN0cmluZyk6IE1pbGVzdG9uZSB8IG51bGw7XG4gKlxuICogY29uc3QgbWlsZXN0b25lU3RvcHM6IFRpbWVUcmF2ZWxTdHJhdGVneTxNaWxlc3RvbmU+ID0ge1xuICogICBzdG9wc0ZvcjogKGxvZywgdHJlZSkgPT5cbiAqICAgICBmaWx0ZXJTdG9wczxNaWxlc3RvbmU+KGNvbW1pdFN0b3BzKGxvZywgdHJlZSksIChzdG9wKSA9PiB7XG4gKiAgICAgICBjb25zdCBtID0gbWlsZXN0b25lRm9yKHN0b3AucnVudGltZVN0YWdlSWQpO1xuICogICAgICAgcmV0dXJuIG0gPyB7IGxhYmVsOiBtLmxhYmVsLCBtZXRhOiBtIH0gOiBudWxsO1xuICogICAgIH0pLFxuICogfTtcbiAqXG4gKiBjb25zdCBjdXJzb3IgPSB0aW1lVHJhdmVsKHNuYXBzaG90LCB7IHN0cmF0ZWd5OiBtaWxlc3RvbmVTdG9wcyB9KTtcbiAqIGN1cnNvci5hdCgpPy5tZXRhPy5raW5kOyAgICAgICAgLy8gJ2xsbS10dXJuJyDigJQgbm8gcmUtZGVyaXZhdGlvblxuICogY3Vyc29yLnN0b3BzWzBdLnByb2xvZ3VlOyAgICAgICAvLyB0cnVlIHdoZW4gc3RhZ2VzIHJhbiBiZWZvcmUgdGhlIGZpcnN0IHR1cm5cbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gZmlsdGVyU3RvcHM8VE1ldGEgPSB1bmtub3duPihcbiAgc3RvcHM6IHJlYWRvbmx5IFN0b3A8dW5rbm93bj5bXSxcbiAga2VlcDogKHN0b3A6IFN0b3A8dW5rbm93bj4pID0+IFN0b3BGaWx0ZXI8VE1ldGE+LFxuKTogU3RvcDxUTWV0YT5bXSB7XG4gIGNvbnN0IGF4aXMgPSBzcGxpdEF4aXMoc3RvcHMpO1xuICBpZiAoIWF4aXMub2spIHtcbiAgICBpZiAoYXhpcy5yZWFzb24gPT09ICdlbXB0eScpIHJldHVybiBbXTtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAnZmlsdGVyU3RvcHM6IGV4cGVjdGVkIGEgYm9va2VuZGVkIGF4aXMg4oCUIFtzdGFydCwg4oCmc3RhZ2VzLCBlbmRdIOKAlCBnb3Qga2luZHMgJyArXG4gICAgICAgIGBbJHtheGlzLmtpbmRzLmpvaW4oJywgJyl9XS4gT25seSBhIHN0cmF0ZWd5IGNhbiBwcm9kdWNlIHRoYXQgc2hhcGU7IGEgcnVuIGNhbm5vdC5gLFxuICAgICk7XG4gIH1cblxuICBjb25zdCBrZXB0OiB7IHN0b3A6IFN0b3A8dW5rbm93bj47IGxhYmVsPzogc3RyaW5nOyBtZXRhPzogVE1ldGEgfVtdID0gW107XG4gIGZvciAoY29uc3Qgc3RvcCBvZiBheGlzLnN0YWdlcykge1xuICAgIGNvbnN0IGRlY2lzaW9uID0ga2VlcChzdG9wKTtcbiAgICBpZiAoIWRlY2lzaW9uKSBjb250aW51ZTtcbiAgICBpZiAoZGVjaXNpb24gPT09IHRydWUpIGtlcHQucHVzaCh7IHN0b3AgfSk7XG4gICAgZWxzZSBrZXB0LnB1c2goeyBzdG9wLCBsYWJlbDogZGVjaXNpb24ubGFiZWwsIG1ldGE6IGRlY2lzaW9uLm1ldGEgfSk7XG4gIH1cblxuICAvLyBUaGUgbG9nJ3MgbGFzdCBpbmRleCwgdGFrZW4gZnJvbSB0aGUgYCdlbmQnYCBib29rZW5kIHJhdGhlciB0aGFuIGEgbGVuZ3RoOlxuICAvLyBgZW5kYCBpcyB0aGUgb25lIHN0b3AgZ3VhcmFudGVlZCB0byBmb2xkIHRoZSB3aG9sZSBsb2csIGFuZCB0aGlzIGZ1bmN0aW9uXG4gIC8vIGlzIG5ldmVyIGhhbmRlZCB0aGUgbG9nIGl0c2VsZi5cbiAgY29uc3QgbGFzdElkeCA9IGF4aXMuZW5kLmxhc3RDb21taXRJZHg7XG4gIGNvbnN0IGZpcnN0ID0ga2VwdFswXTtcbiAgY29uc3Qgb3V0OiBTdG9wPFRNZXRhPltdID0gW1xuICAgIHtcbiAgICAgIC4uLnJldHlwZWQ8VE1ldGE+KGF4aXMuc3RhcnQpLFxuICAgICAgc3RlcDogMCxcbiAgICAgIGxhc3RDb21taXRJZHg6IGZpcnN0ID8gZmlyc3Quc3RvcC5jb21taXRJZHggLSAxIDogbGFzdElkeCxcbiAgICAgIC8vIE9ubHkgd2hlbiBhIFNUQUdFIHdhcyBhY3R1YWxseSBhYnNvcmJlZC4gQW4gYXhpcyB0aGF0IGtlcHQgZXZlcnl0aGluZ1xuICAgICAgLy8gaGFzIHRoZSBzYW1lIHN0YXJ0IGl0IGFsd2F5cyBoYWQsIGFuZCBzYXlzIG5vdGhpbmcgaXQgbmVlZCBub3Qgc2F5LlxuICAgICAgLi4uKGZpcnN0ICYmIGZpcnN0LnN0b3Auc3RlcCA+IDEgPyB7IHByb2xvZ3VlOiB0cnVlIGFzIGNvbnN0IH0gOiB7fSksXG4gICAgICAuLi4oIWZpcnN0ICYmIGF4aXMuc3RhZ2VzLmxlbmd0aCA+IDAgPyB7IHByb2xvZ3VlOiB0cnVlIGFzIGNvbnN0IH0gOiB7fSksXG4gICAgfSxcbiAgXTtcblxuICBmb3IgKGNvbnN0IFtpLCByb3ddIG9mIGtlcHQuZW50cmllcygpKSB7XG4gICAgY29uc3QgbmV4dCA9IGtlcHRbaSArIDFdO1xuICAgIG91dC5wdXNoKHtcbiAgICAgIC4uLnJldHlwZWQ8VE1ldGE+KHJvdy5zdG9wKSxcbiAgICAgIHN0ZXA6IG91dC5sZW5ndGgsXG4gICAgICBsYXN0Q29tbWl0SWR4OiBuZXh0ID8gbmV4dC5zdG9wLmNvbW1pdElkeCAtIDEgOiBsYXN0SWR4LFxuICAgICAgLi4uKHJvdy5sYWJlbCAhPT0gdW5kZWZpbmVkID8geyBsYWJlbDogcm93LmxhYmVsIH0gOiB7fSksXG4gICAgICAuLi4ocm93Lm1ldGEgIT09IHVuZGVmaW5lZCA/IHsgbWV0YTogcm93Lm1ldGEgfSA6IHt9KSxcbiAgICB9KTtcbiAgfVxuXG4gIG91dC5wdXNoKHsgLi4ucmV0eXBlZDxUTWV0YT4oYXhpcy5lbmQpLCBzdGVwOiBvdXQubGVuZ3RoIH0pO1xuICByZXR1cm4gb3V0O1xufVxuIl19
|