footprintjs 9.48.2 → 10.0.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.
- package/AGENTS.md +12 -10
- package/CLAUDE.md +21 -23
- package/README.md +1 -1
- package/dist/advanced.js +71 -128
- package/dist/esm/advanced.d.ts +24 -58
- package/dist/esm/advanced.js +13 -51
- package/dist/esm/index.d.ts +5 -8
- package/dist/esm/index.js +3 -3
- package/dist/esm/lib/builder/FlowChartBuilder.d.ts +1 -1
- package/dist/esm/lib/builder/FlowChartBuilder.js +3 -3
- package/dist/esm/lib/builder/structure/StructureRecorder.d.ts +1 -1
- package/dist/esm/lib/builder/structure/StructureRecorder.js +1 -1
- package/dist/esm/lib/capture/index.d.ts +0 -1
- package/dist/esm/lib/capture/index.js +1 -2
- package/dist/esm/lib/engine/graph/prefixNodeTree.js +2 -2
- package/dist/esm/lib/engine/handlers/ResumeEntry.d.ts +3 -3
- package/dist/esm/lib/engine/handlers/ResumeEntry.js +4 -4
- package/dist/esm/lib/engine/handlers/SubflowExecutor.d.ts +1 -2
- package/dist/esm/lib/engine/handlers/SubflowExecutor.js +4 -8
- package/dist/esm/lib/engine/index.d.ts +1 -1
- package/dist/esm/lib/engine/index.js +1 -1
- package/dist/esm/lib/engine/narrative/CombinedNarrativeRecorder.d.ts +4 -4
- package/dist/esm/lib/engine/narrative/CombinedNarrativeRecorder.js +1 -1
- package/dist/esm/lib/engine/narrative/index.d.ts +1 -1
- package/dist/esm/lib/engine/narrative/index.js +1 -1
- package/dist/esm/lib/engine/narrative/narrativeTypes.d.ts +1 -11
- package/dist/esm/lib/engine/narrative/narrativeTypes.js +1 -1
- package/dist/esm/lib/engine/traversal/FlowchartTraverser.d.ts +2 -10
- package/dist/esm/lib/engine/traversal/FlowchartTraverser.js +4 -6
- package/dist/esm/lib/engine/traversalContext.d.ts +1 -1
- package/dist/esm/lib/engine/traversalContext.js +2 -2
- package/dist/esm/lib/engine/types.d.ts +2 -10
- package/dist/esm/lib/engine/types.js +1 -1
- package/dist/esm/lib/engine/walkSubflowSpec.js +2 -2
- package/dist/esm/lib/ids/reservedIds.js +2 -2
- package/dist/esm/lib/memory/DiagnosticCollector.js +2 -2
- package/dist/esm/lib/memory/StageContext.d.ts +2 -4
- package/dist/esm/lib/memory/StageContext.js +2 -2
- package/dist/esm/lib/memory/borrowedMutation.js +2 -2
- package/dist/esm/lib/memory/index.d.ts +6 -21
- package/dist/esm/lib/memory/index.js +4 -22
- package/dist/esm/lib/memory/redaction.d.ts +1 -1
- package/dist/esm/lib/memory/redaction.js +2 -2
- package/dist/esm/lib/memory/runPolicy.d.ts +3 -2
- package/dist/esm/lib/memory/runPolicy.js +1 -1
- package/dist/esm/lib/reactive/createTypedScope.js +2 -2
- package/dist/esm/lib/reactive/writeTraps.js +2 -2
- package/dist/esm/lib/recorder/ControlDepRecorder.d.ts +3 -2
- package/dist/esm/lib/recorder/ControlDepRecorder.js +3 -2
- package/dist/esm/lib/recorder/EmitRecorder.d.ts +1 -1
- package/dist/esm/lib/recorder/EmitRecorder.js +1 -1
- package/dist/esm/lib/recorder/InOutRecorder.js +2 -2
- package/dist/esm/lib/recorder/qualityTrace.d.ts +1 -1
- package/dist/esm/lib/recorder/qualityTrace.js +2 -2
- package/dist/esm/lib/runner/DeferredObserverTier.js +2 -2
- package/dist/esm/lib/runner/ExecutionRuntime.d.ts +4 -5
- package/dist/esm/lib/runner/ExecutionRuntime.js +2 -5
- package/dist/esm/lib/runner/FlowChartExecutor.d.ts +1 -1
- package/dist/esm/lib/runner/FlowChartExecutor.js +1 -1
- package/dist/esm/lib/runner/getSubtreeSnapshot.d.ts +1 -1
- package/dist/esm/lib/runner/getSubtreeSnapshot.js +4 -4
- package/dist/esm/lib/runner/resume.js +2 -2
- package/dist/esm/lib/runner/snapshot.js +3 -2
- package/dist/esm/lib/scope/ScopeFacade.js +2 -2
- package/dist/esm/lib/scope/state/zod/scopeFactory.js +2 -2
- package/dist/esm/recorders.d.ts +2 -3
- package/dist/esm/recorders.js +1 -1
- package/dist/esm/trace.d.ts +11 -57
- package/dist/esm/trace.js +10 -68
- package/dist/index.js +3 -3
- package/dist/lib/builder/FlowChartBuilder.js +5 -5
- package/dist/lib/builder/structure/StructureRecorder.js +1 -1
- package/dist/lib/capture/index.js +2 -4
- package/dist/lib/engine/graph/prefixNodeTree.js +5 -5
- package/dist/lib/engine/handlers/ResumeEntry.js +4 -4
- package/dist/lib/engine/handlers/SubflowExecutor.js +5 -9
- package/dist/lib/engine/index.js +1 -1
- package/dist/lib/engine/narrative/CombinedNarrativeRecorder.js +1 -1
- package/dist/lib/engine/narrative/index.js +1 -1
- package/dist/lib/engine/narrative/narrativeTypes.js +1 -1
- package/dist/lib/engine/traversal/FlowchartTraverser.js +8 -10
- package/dist/lib/engine/traversalContext.js +4 -4
- package/dist/lib/engine/types.js +1 -1
- package/dist/lib/engine/walkSubflowSpec.js +3 -3
- package/dist/lib/ids/reservedIds.js +5 -5
- package/dist/lib/memory/DiagnosticCollector.js +3 -3
- package/dist/lib/memory/StageContext.js +3 -3
- package/dist/lib/memory/borrowedMutation.js +3 -3
- package/dist/lib/memory/index.js +7 -42
- package/dist/lib/memory/redaction.js +3 -3
- package/dist/lib/memory/runPolicy.js +1 -1
- package/dist/lib/reactive/createTypedScope.js +3 -3
- package/dist/lib/reactive/writeTraps.js +4 -4
- package/dist/lib/recorder/ControlDepRecorder.js +3 -2
- package/dist/lib/recorder/EmitRecorder.js +1 -1
- package/dist/lib/recorder/InOutRecorder.js +3 -3
- package/dist/lib/recorder/qualityTrace.js +4 -4
- package/dist/lib/runner/DeferredObserverTier.js +3 -3
- package/dist/lib/runner/ExecutionRuntime.js +6 -9
- package/dist/lib/runner/FlowChartExecutor.js +1 -1
- package/dist/lib/runner/getSubtreeSnapshot.js +6 -6
- package/dist/lib/runner/resume.js +3 -3
- package/dist/lib/runner/snapshot.js +6 -5
- package/dist/lib/scope/ScopeFacade.js +3 -3
- package/dist/lib/scope/state/zod/scopeFactory.js +4 -4
- package/dist/recorders.js +1 -1
- package/dist/trace.js +18 -120
- package/dist/types/advanced.d.ts +24 -58
- package/dist/types/index.d.ts +5 -8
- package/dist/types/lib/builder/FlowChartBuilder.d.ts +1 -1
- package/dist/types/lib/builder/structure/StructureRecorder.d.ts +1 -1
- package/dist/types/lib/capture/index.d.ts +0 -1
- package/dist/types/lib/engine/handlers/ResumeEntry.d.ts +3 -3
- package/dist/types/lib/engine/handlers/SubflowExecutor.d.ts +1 -2
- package/dist/types/lib/engine/index.d.ts +1 -1
- package/dist/types/lib/engine/narrative/CombinedNarrativeRecorder.d.ts +4 -4
- package/dist/types/lib/engine/narrative/index.d.ts +1 -1
- package/dist/types/lib/engine/narrative/narrativeTypes.d.ts +1 -11
- package/dist/types/lib/engine/traversal/FlowchartTraverser.d.ts +2 -10
- package/dist/types/lib/engine/traversalContext.d.ts +1 -1
- package/dist/types/lib/engine/types.d.ts +2 -10
- package/dist/types/lib/memory/StageContext.d.ts +2 -4
- package/dist/types/lib/memory/index.d.ts +6 -21
- package/dist/types/lib/memory/redaction.d.ts +1 -1
- package/dist/types/lib/memory/runPolicy.d.ts +3 -2
- package/dist/types/lib/recorder/ControlDepRecorder.d.ts +3 -2
- package/dist/types/lib/recorder/EmitRecorder.d.ts +1 -1
- package/dist/types/lib/recorder/qualityTrace.d.ts +1 -1
- package/dist/types/lib/runner/ExecutionRuntime.d.ts +4 -5
- package/dist/types/lib/runner/FlowChartExecutor.d.ts +1 -1
- package/dist/types/lib/runner/getSubtreeSnapshot.d.ts +1 -1
- package/dist/types/recorders.d.ts +2 -3
- package/dist/types/trace.d.ts +11 -57
- package/package.json +6 -15
- package/dist/esm/lib/capture/freeze.d.ts +0 -91
- package/dist/esm/lib/capture/freeze.js +0 -314
- package/dist/esm/lib/capture/ownData.d.ts +0 -7
- package/dist/esm/lib/capture/ownData.js +0 -15
- package/dist/esm/lib/capture/valueKinds.d.ts +0 -57
- package/dist/esm/lib/capture/valueKinds.js +0 -142
- package/dist/esm/lib/ids/runtimeStageId.d.ts +0 -173
- package/dist/esm/lib/ids/runtimeStageId.js +0 -194
- package/dist/esm/lib/memory/EventLog.d.ts +0 -105
- package/dist/esm/lib/memory/EventLog.js +0 -148
- package/dist/esm/lib/memory/RecordFrame.d.ts +0 -232
- package/dist/esm/lib/memory/RecordFrame.js +0 -296
- package/dist/esm/lib/memory/SharedMemory.d.ts +0 -46
- package/dist/esm/lib/memory/SharedMemory.js +0 -88
- package/dist/esm/lib/memory/TransactionBuffer.d.ts +0 -521
- package/dist/esm/lib/memory/TransactionBuffer.js +0 -946
- package/dist/esm/lib/memory/admission.d.ts +0 -81
- package/dist/esm/lib/memory/admission.js +0 -153
- package/dist/esm/lib/memory/backtrack.d.ts +0 -286
- package/dist/esm/lib/memory/backtrack.js +0 -457
- package/dist/esm/lib/memory/commitLogUtils.d.ts +0 -217
- package/dist/esm/lib/memory/commitLogUtils.js +0 -384
- package/dist/esm/lib/memory/deltaEncoding.d.ts +0 -66
- package/dist/esm/lib/memory/deltaEncoding.js +0 -122
- package/dist/esm/lib/memory/equality.d.ts +0 -93
- package/dist/esm/lib/memory/equality.js +0 -262
- package/dist/esm/lib/memory/eventPosition.d.ts +0 -18
- package/dist/esm/lib/memory/eventPosition.js +0 -2
- package/dist/esm/lib/memory/honesty.d.ts +0 -93
- package/dist/esm/lib/memory/honesty.js +0 -92
- package/dist/esm/lib/memory/keyPaths.d.ts +0 -125
- package/dist/esm/lib/memory/keyPaths.js +0 -227
- package/dist/esm/lib/memory/logModel.d.ts +0 -76
- package/dist/esm/lib/memory/logModel.js +0 -364
- package/dist/esm/lib/memory/merge.d.ts +0 -26
- package/dist/esm/lib/memory/merge.js +0 -60
- package/dist/esm/lib/memory/pathOps.d.ts +0 -115
- package/dist/esm/lib/memory/pathOps.js +0 -290
- package/dist/esm/lib/memory/paths.d.ts +0 -52
- package/dist/esm/lib/memory/paths.js +0 -57
- package/dist/esm/lib/memory/placeholders.d.ts +0 -39
- package/dist/esm/lib/memory/placeholders.js +0 -40
- package/dist/esm/lib/memory/recordCommit.d.ts +0 -45
- package/dist/esm/lib/memory/recordCommit.js +0 -61
- package/dist/esm/lib/memory/scrub.d.ts +0 -53
- package/dist/esm/lib/memory/scrub.js +0 -74
- package/dist/esm/lib/memory/types.d.ts +0 -209
- package/dist/esm/lib/memory/types.js +0 -10
- package/dist/esm/lib/memory/utils.d.ts +0 -73
- package/dist/esm/lib/memory/utils.js +0 -159
- package/dist/esm/lib/memory/verbs.d.ts +0 -333
- package/dist/esm/lib/memory/verbs.js +0 -427
- package/dist/esm/lib/recorder/CommitRangeIndex.d.ts +0 -147
- package/dist/esm/lib/recorder/CommitRangeIndex.js +0 -207
- package/dist/esm/lib/scope/detectCircular.d.ts +0 -13
- package/dist/esm/lib/scope/detectCircular.js +0 -14
- package/dist/esm/lib/scope/recorders/summarizeValue.d.ts +0 -5
- package/dist/esm/lib/scope/recorders/summarizeValue.js +0 -6
- package/dist/esm/lib/slice/elementProvenance.d.ts +0 -81
- package/dist/esm/lib/slice/elementProvenance.js +0 -190
- package/dist/esm/lib/slice/forwardSliceForKey.d.ts +0 -88
- package/dist/esm/lib/slice/forwardSliceForKey.js +0 -243
- package/dist/esm/lib/slice/index.d.ts +0 -25
- package/dist/esm/lib/slice/index.js +0 -25
- package/dist/esm/lib/slice/keyIndex.d.ts +0 -137
- package/dist/esm/lib/slice/keyIndex.js +0 -293
- package/dist/esm/lib/slice/keyTimeline.d.ts +0 -49
- package/dist/esm/lib/slice/keyTimeline.js +0 -113
- package/dist/esm/lib/slice/keysReadSources.d.ts +0 -51
- package/dist/esm/lib/slice/keysReadSources.js +0 -95
- package/dist/esm/lib/slice/serialize.d.ts +0 -78
- package/dist/esm/lib/slice/serialize.js +0 -278
- package/dist/esm/lib/slice/sliceForKey.d.ts +0 -47
- package/dist/esm/lib/slice/sliceForKey.js +0 -88
- package/dist/esm/lib/slice/types.d.ts +0 -567
- package/dist/esm/lib/slice/types.js +0 -25
- package/dist/esm/lib/time-travel/axis.d.ts +0 -119
- package/dist/esm/lib/time-travel/axis.js +0 -179
- package/dist/esm/lib/time-travel/bundles.d.ts +0 -77
- package/dist/esm/lib/time-travel/bundles.js +0 -136
- package/dist/esm/lib/time-travel/chain.d.ts +0 -93
- package/dist/esm/lib/time-travel/chain.js +0 -188
- package/dist/esm/lib/time-travel/commitStops.d.ts +0 -55
- package/dist/esm/lib/time-travel/commitStops.js +0 -202
- package/dist/esm/lib/time-travel/index.d.ts +0 -22
- package/dist/esm/lib/time-travel/index.js +0 -21
- package/dist/esm/lib/time-travel/stateAt.d.ts +0 -102
- package/dist/esm/lib/time-travel/stateAt.js +0 -153
- package/dist/esm/lib/time-travel/tagStops.d.ts +0 -72
- package/dist/esm/lib/time-travel/tagStops.js +0 -102
- package/dist/esm/lib/time-travel/timeTravel.d.ts +0 -70
- package/dist/esm/lib/time-travel/timeTravel.js +0 -360
- package/dist/esm/lib/time-travel/types.d.ts +0 -470
- package/dist/esm/lib/time-travel/types.js +0 -23
- package/dist/esm/write.d.ts +0 -47
- package/dist/esm/write.js +0 -46
- package/dist/lib/capture/freeze.js +0 -320
- package/dist/lib/capture/ownData.js +0 -19
- package/dist/lib/capture/valueKinds.js +0 -146
- package/dist/lib/ids/runtimeStageId.js +0 -210
- package/dist/lib/memory/EventLog.js +0 -152
- package/dist/lib/memory/RecordFrame.js +0 -300
- package/dist/lib/memory/SharedMemory.js +0 -92
- package/dist/lib/memory/TransactionBuffer.js +0 -950
- package/dist/lib/memory/admission.js +0 -159
- package/dist/lib/memory/backtrack.js +0 -463
- package/dist/lib/memory/commitLogUtils.js +0 -399
- package/dist/lib/memory/deltaEncoding.js +0 -128
- package/dist/lib/memory/equality.js +0 -266
- package/dist/lib/memory/eventPosition.js +0 -3
- package/dist/lib/memory/honesty.js +0 -95
- package/dist/lib/memory/keyPaths.js +0 -243
- package/dist/lib/memory/logModel.js +0 -372
- package/dist/lib/memory/merge.js +0 -64
- package/dist/lib/memory/pathOps.js +0 -306
- package/dist/lib/memory/paths.js +0 -62
- package/dist/lib/memory/placeholders.js +0 -43
- package/dist/lib/memory/recordCommit.js +0 -65
- package/dist/lib/memory/scrub.js +0 -79
- package/dist/lib/memory/types.js +0 -11
- package/dist/lib/memory/utils.js +0 -178
- package/dist/lib/memory/verbs.js +0 -444
- package/dist/lib/recorder/CommitRangeIndex.js +0 -211
- package/dist/lib/scope/detectCircular.js +0 -21
- package/dist/lib/scope/recorders/summarizeValue.js +0 -10
- package/dist/lib/slice/elementProvenance.js +0 -195
- package/dist/lib/slice/forwardSliceForKey.js +0 -247
- package/dist/lib/slice/index.js +0 -42
- package/dist/lib/slice/keyIndex.js +0 -313
- package/dist/lib/slice/keyTimeline.js +0 -117
- package/dist/lib/slice/keysReadSources.js +0 -101
- package/dist/lib/slice/serialize.js +0 -286
- package/dist/lib/slice/sliceForKey.js +0 -93
- package/dist/lib/slice/types.js +0 -26
- package/dist/lib/time-travel/axis.js +0 -184
- package/dist/lib/time-travel/bundles.js +0 -144
- package/dist/lib/time-travel/chain.js +0 -193
- package/dist/lib/time-travel/commitStops.js +0 -206
- package/dist/lib/time-travel/index.js +0 -32
- package/dist/lib/time-travel/stateAt.js +0 -160
- package/dist/lib/time-travel/tagStops.js +0 -106
- package/dist/lib/time-travel/timeTravel.js +0 -364
- package/dist/lib/time-travel/types.js +0 -24
- package/dist/types/lib/capture/freeze.d.ts +0 -91
- package/dist/types/lib/capture/ownData.d.ts +0 -7
- package/dist/types/lib/capture/valueKinds.d.ts +0 -57
- package/dist/types/lib/ids/runtimeStageId.d.ts +0 -173
- package/dist/types/lib/memory/EventLog.d.ts +0 -105
- package/dist/types/lib/memory/RecordFrame.d.ts +0 -232
- package/dist/types/lib/memory/SharedMemory.d.ts +0 -46
- package/dist/types/lib/memory/TransactionBuffer.d.ts +0 -521
- package/dist/types/lib/memory/admission.d.ts +0 -81
- package/dist/types/lib/memory/backtrack.d.ts +0 -286
- package/dist/types/lib/memory/commitLogUtils.d.ts +0 -217
- package/dist/types/lib/memory/deltaEncoding.d.ts +0 -66
- package/dist/types/lib/memory/equality.d.ts +0 -93
- package/dist/types/lib/memory/eventPosition.d.ts +0 -18
- package/dist/types/lib/memory/honesty.d.ts +0 -93
- package/dist/types/lib/memory/keyPaths.d.ts +0 -125
- package/dist/types/lib/memory/logModel.d.ts +0 -76
- package/dist/types/lib/memory/merge.d.ts +0 -26
- package/dist/types/lib/memory/pathOps.d.ts +0 -115
- package/dist/types/lib/memory/paths.d.ts +0 -52
- package/dist/types/lib/memory/placeholders.d.ts +0 -39
- package/dist/types/lib/memory/recordCommit.d.ts +0 -45
- package/dist/types/lib/memory/scrub.d.ts +0 -53
- package/dist/types/lib/memory/types.d.ts +0 -209
- package/dist/types/lib/memory/utils.d.ts +0 -73
- package/dist/types/lib/memory/verbs.d.ts +0 -333
- package/dist/types/lib/recorder/CommitRangeIndex.d.ts +0 -147
- package/dist/types/lib/scope/detectCircular.d.ts +0 -13
- package/dist/types/lib/scope/recorders/summarizeValue.d.ts +0 -5
- package/dist/types/lib/slice/elementProvenance.d.ts +0 -81
- package/dist/types/lib/slice/forwardSliceForKey.d.ts +0 -88
- package/dist/types/lib/slice/index.d.ts +0 -25
- package/dist/types/lib/slice/keyIndex.d.ts +0 -137
- package/dist/types/lib/slice/keyTimeline.d.ts +0 -49
- package/dist/types/lib/slice/keysReadSources.d.ts +0 -51
- package/dist/types/lib/slice/serialize.d.ts +0 -78
- package/dist/types/lib/slice/sliceForKey.d.ts +0 -47
- package/dist/types/lib/slice/types.d.ts +0 -567
- package/dist/types/lib/time-travel/axis.d.ts +0 -119
- package/dist/types/lib/time-travel/bundles.d.ts +0 -77
- package/dist/types/lib/time-travel/chain.d.ts +0 -93
- package/dist/types/lib/time-travel/commitStops.d.ts +0 -55
- package/dist/types/lib/time-travel/index.d.ts +0 -22
- package/dist/types/lib/time-travel/stateAt.d.ts +0 -102
- package/dist/types/lib/time-travel/tagStops.d.ts +0 -72
- package/dist/types/lib/time-travel/timeTravel.d.ts +0 -70
- package/dist/types/lib/time-travel/types.d.ts +0 -470
- package/dist/types/write.d.ts +0 -47
- package/dist/write.js +0 -52
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* keyPaths.ts — which rows of a commit log touch a state key. ONE answer (F3, 9.33.0).
|
|
4
|
-
*
|
|
5
|
-
* WHY THIS FILE EXISTS. A key query (`commitValueAt`, `findLastWriter`, `causalChain`, the slice
|
|
6
|
-
* layer) asks "which rows wrote `key`?". Each reader used to answer with its own `row.path === key`,
|
|
7
|
-
* so a row written INSIDE the key — `cfg␟b`, which every subflow seed of an object, every
|
|
8
|
-
* outputMapper merge-back and every fork child's namespace produces — was invisible to all of
|
|
9
|
-
* them, while the fold (`stateAt`, the live commit) applied it. The fold said `{a:1,b:2}`; the key
|
|
10
|
-
* queries said "never written". Every reader now asks here.
|
|
11
|
-
*
|
|
12
|
-
* THE PATH HALF (this file, L0 — it imports only the path codec and types):
|
|
13
|
-
* - {@link relation} — how a row's path sits against a key's path. A segment prefix on the
|
|
14
|
-
* DELIM-joined path, the way RFC 6901 prefixes a JSON Pointer: `cfg` is a prefix of `cfg␟a`,
|
|
15
|
-
* never of `cfgX`. A row is `'exact'` (on the key), `'inside'` (below it — it wrote part of the
|
|
16
|
-
* key's value) or `'around'` (above it — it wrote a container that holds the key).
|
|
17
|
-
* - {@link buildWriterIndex} / {@link writerCandidates} — one pass over a log, then the rows that
|
|
18
|
-
* can have written a key, found through its top-level key instead of a scan.
|
|
19
|
-
*
|
|
20
|
-
* THE RULES (defined here; the fold is L1 and the log readers L3, so `commitLogUtils.ts` applies
|
|
21
|
-
* them — `writersOf`, `findLastWriter`, `commitValueAt`):
|
|
22
|
-
* - THE WRITER RULE — commit `c` WRITES key `K` iff `c` has a row `'exact'` or `'inside'` `K`,
|
|
23
|
-
* or a row `'around'` `K` across which the value at `K` differs (compared over the whole commit,
|
|
24
|
-
* not row by row: a value that changes and changes back inside one commit was not written).
|
|
25
|
-
* A top-level key has no `'around'` rows, so for it the rule is the path check alone.
|
|
26
|
-
* Why not every `'around'` row: `$update('cfg', { list: [3] })` is a `merge` row on `cfg`, but
|
|
27
|
-
* it never reaches `cfg␟a` — counting it named the wrong writer of `cfg␟a`.
|
|
28
|
-
* - THE VALUE RULE — the value of `K` at commit `i` is the fold of EVERY row under `K`'s top-level
|
|
29
|
-
* key up to `i`, anchored at that key's last `set`/`delete`, read at `K`: the fold `stateAt`
|
|
30
|
-
* does, restricted to one top-level key. Top-level keys never interact under the step, so the
|
|
31
|
-
* restriction is exact. Folding only the rows that touch `K` is NOT: an array union
|
|
32
|
-
* (`deepSmartMerge`) dedups the whole array, so a sibling element written beside `a␟1` changes
|
|
33
|
-
* where a later merge on `a` leaves `a[1]`.
|
|
34
|
-
*
|
|
35
|
-
* @example
|
|
36
|
-
* ```typescript
|
|
37
|
-
* relation('cfg\u001Fb', 'cfg'); // 'inside' — the row wrote part of cfg
|
|
38
|
-
* relation('cfg', 'cfg\u001Fa'); // 'around' — the row wrote the container cfg.a lives in
|
|
39
|
-
* relation('cfgX', 'cfg'); // undefined — a different key, not a prefix match
|
|
40
|
-
* ```
|
|
41
|
-
*/
|
|
42
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
-
exports.writesOnlyInside = exports.ascendingUnion = exports.writerCandidates = exports.between = exports.lastBefore = exports.lowerBound = exports.subtreePositions = exports.ancestorNodes = exports.nodeAt = exports.pathsWritten = exports.buildWriterIndex = exports.rootOf = exports.relation = exports.queryWork = void 0;
|
|
44
|
-
const paths_js_1 = require("./paths.js");
|
|
45
|
-
/**
|
|
46
|
-
* The WORK every key query has done — rows indexed and scanned, fold steps, around-verdicts, trie and
|
|
47
|
-
* ancestor steps, binary searches, a causal walk's own loops — summed across calls. A deterministic cost
|
|
48
|
-
* measure: `test/lib/memory/boundary/key-query-scaling.test.ts` asserts a causal walk's work grows linearly
|
|
49
|
-
* in the log by COUNTING it (a wall-clock ratio failed on a busy machine). Never read by the library; one
|
|
50
|
-
* integer add per unit of work it already does. Here, at L0, so every layer that does that work can count it.
|
|
51
|
-
*/
|
|
52
|
-
exports.queryWork = { units: 0 };
|
|
53
|
-
const DELIM_CODE = paths_js_1.DELIM.charCodeAt(0);
|
|
54
|
-
/**
|
|
55
|
-
* How the row path `rowPath` sits against the key `key` — both DELIM-joined `TraceEntry.path`
|
|
56
|
-
* strings (a top-level key is a one-segment path). `'exact'` when they are equal, `'inside'` when
|
|
57
|
-
* the row is below the key, `'around'` when the row is above it, `undefined` when neither is a
|
|
58
|
-
* segment prefix of the other.
|
|
59
|
-
*/
|
|
60
|
-
function relation(rowPath, key) {
|
|
61
|
-
if (rowPath === key)
|
|
62
|
-
return 'exact';
|
|
63
|
-
if (rowPath.length > key.length) {
|
|
64
|
-
return rowPath.charCodeAt(key.length) === DELIM_CODE && rowPath.startsWith(key) ? 'inside' : undefined;
|
|
65
|
-
}
|
|
66
|
-
return key.charCodeAt(rowPath.length) === DELIM_CODE && key.startsWith(rowPath) ? 'around' : undefined;
|
|
67
|
-
}
|
|
68
|
-
exports.relation = relation;
|
|
69
|
-
/** The top-level key a DELIM-joined path belongs to — its first segment. */
|
|
70
|
-
function rootOf(path) {
|
|
71
|
-
const cut = path.indexOf(paths_js_1.DELIM);
|
|
72
|
-
return cut === -1 ? path : path.slice(0, cut);
|
|
73
|
-
}
|
|
74
|
-
exports.rootOf = rootOf;
|
|
75
|
-
function nodeOf(path) {
|
|
76
|
-
return { path, positions: [], totals: [], writes: [], children: new Map() };
|
|
77
|
-
}
|
|
78
|
-
/** Append `i` to an ascending list unless it is already its last element. */
|
|
79
|
-
function pushOnce(list, i) {
|
|
80
|
-
if (list[list.length - 1] !== i)
|
|
81
|
-
list.push(i);
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* One pass over `commitLog`: the path trie of every written path. Build it ONCE when a reader asks about
|
|
85
|
-
* many keys (a causal walk, a forward slice) — or let `commitLogUtils · logModel` memoise it for a frozen log.
|
|
86
|
-
*/
|
|
87
|
-
function buildWriterIndex(commitLog) {
|
|
88
|
-
const roots = new Map();
|
|
89
|
-
for (let i = 0; i < commitLog.length; i++) {
|
|
90
|
-
const trace = commitLog[i].trace;
|
|
91
|
-
for (let row = 0; row < trace.length; row++) {
|
|
92
|
-
const { path, verb } = trace[row];
|
|
93
|
-
const segs = path.split(paths_js_1.DELIM);
|
|
94
|
-
let node = roots.get(segs[0]);
|
|
95
|
-
if (node === undefined) {
|
|
96
|
-
node = nodeOf(segs[0]);
|
|
97
|
-
roots.set(segs[0], node);
|
|
98
|
-
}
|
|
99
|
-
for (let s = 1; s < segs.length; s++) {
|
|
100
|
-
let child = node.children.get(segs[s]);
|
|
101
|
-
if (child === undefined) {
|
|
102
|
-
child = nodeOf(node.path + paths_js_1.DELIM + segs[s]);
|
|
103
|
-
node.children.set(segs[s], child);
|
|
104
|
-
}
|
|
105
|
-
node = child;
|
|
106
|
-
}
|
|
107
|
-
pushOnce(node.positions, i);
|
|
108
|
-
if (verb === 'set' || verb === 'delete')
|
|
109
|
-
pushOnce(node.totals, i);
|
|
110
|
-
if (verb !== 'delete')
|
|
111
|
-
pushOnce(node.writes, i);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
return { roots };
|
|
115
|
-
}
|
|
116
|
-
exports.buildWriterIndex = buildWriterIndex;
|
|
117
|
-
/** Every path a row was written on, in trie order. */
|
|
118
|
-
function pathsWritten(index) {
|
|
119
|
-
const out = [];
|
|
120
|
-
const stack = [...index.roots.values()];
|
|
121
|
-
while (stack.length > 0) {
|
|
122
|
-
const node = stack.pop();
|
|
123
|
-
if (node.positions.length > 0)
|
|
124
|
-
out.push(node.path);
|
|
125
|
-
for (const child of node.children.values())
|
|
126
|
-
stack.push(child);
|
|
127
|
-
}
|
|
128
|
-
return out;
|
|
129
|
-
}
|
|
130
|
-
exports.pathsWritten = pathsWritten;
|
|
131
|
-
/** The node for `key`, or undefined when no row was written on it or below it. */
|
|
132
|
-
function nodeAt(index, key) {
|
|
133
|
-
const segs = key.split(paths_js_1.DELIM);
|
|
134
|
-
exports.queryWork.units += segs.length;
|
|
135
|
-
let node = index.roots.get(segs[0]);
|
|
136
|
-
for (let s = 1; node !== undefined && s < segs.length; s++)
|
|
137
|
-
node = node.children.get(segs[s]);
|
|
138
|
-
return node;
|
|
139
|
-
}
|
|
140
|
-
exports.nodeAt = nodeAt;
|
|
141
|
-
/** The nodes of `key`'s PROPER ancestors that exist in the index, top-level key first. */
|
|
142
|
-
function ancestorNodes(index, key) {
|
|
143
|
-
const segs = key.split(paths_js_1.DELIM);
|
|
144
|
-
const out = [];
|
|
145
|
-
exports.queryWork.units += segs.length;
|
|
146
|
-
let node = index.roots.get(segs[0]);
|
|
147
|
-
for (let s = 1; node !== undefined && s < segs.length; s++) {
|
|
148
|
-
out.push(node);
|
|
149
|
-
node = node.children.get(segs[s]);
|
|
150
|
-
}
|
|
151
|
-
return out;
|
|
152
|
-
}
|
|
153
|
-
exports.ancestorNodes = ancestorNodes;
|
|
154
|
-
/** Every commit with a row on `node`'s path or below it — ascending, memoised on the node. */
|
|
155
|
-
function subtreePositions(node) {
|
|
156
|
-
exports.queryWork.units += 1;
|
|
157
|
-
if (node.subtree === undefined) {
|
|
158
|
-
if (node.children.size === 0)
|
|
159
|
-
node.subtree = node.positions;
|
|
160
|
-
else {
|
|
161
|
-
const lists = [node.positions];
|
|
162
|
-
for (const child of node.children.values())
|
|
163
|
-
lists.push(subtreePositions(child));
|
|
164
|
-
node.subtree = ascendingUnion(lists);
|
|
165
|
-
exports.queryWork.units += node.subtree.length;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
return node.subtree;
|
|
169
|
-
}
|
|
170
|
-
exports.subtreePositions = subtreePositions;
|
|
171
|
-
/** The first index in an ascending list holding a value >= `value`. */
|
|
172
|
-
function lowerBound(sorted, value) {
|
|
173
|
-
exports.queryWork.units += 1;
|
|
174
|
-
let lo = 0;
|
|
175
|
-
let hi = sorted.length;
|
|
176
|
-
while (lo < hi) {
|
|
177
|
-
const mid = (lo + hi) >>> 1;
|
|
178
|
-
if (sorted[mid] < value)
|
|
179
|
-
lo = mid + 1;
|
|
180
|
-
else
|
|
181
|
-
hi = mid;
|
|
182
|
-
}
|
|
183
|
-
return lo;
|
|
184
|
-
}
|
|
185
|
-
exports.lowerBound = lowerBound;
|
|
186
|
-
/** The last value in an ascending list that is < `before`, or -1. */
|
|
187
|
-
function lastBefore(sorted, before) {
|
|
188
|
-
const at = lowerBound(sorted, before);
|
|
189
|
-
return at > 0 ? sorted[at - 1] : -1;
|
|
190
|
-
}
|
|
191
|
-
exports.lastBefore = lastBefore;
|
|
192
|
-
/** The values of an ascending list in the OPEN range (`after`, `before`). */
|
|
193
|
-
function between(sorted, after, before) {
|
|
194
|
-
const out = sorted.slice(lowerBound(sorted, after + 1), lowerBound(sorted, before));
|
|
195
|
-
exports.queryWork.units += out.length;
|
|
196
|
-
return out;
|
|
197
|
-
}
|
|
198
|
-
exports.between = between;
|
|
199
|
-
/** The path half of the writer rule over an index: every commit that can have written `key`. `O(depth + matches)`. */
|
|
200
|
-
function writerCandidates(index, key) {
|
|
201
|
-
const node = nodeAt(index, key);
|
|
202
|
-
const written = node === undefined ? [] : subtreePositions(node);
|
|
203
|
-
const ancestors = ancestorNodes(index, key);
|
|
204
|
-
if (ancestors.length === 0)
|
|
205
|
-
return { atOrInside: written, aroundOnly: [] };
|
|
206
|
-
const already = new Set(written);
|
|
207
|
-
return {
|
|
208
|
-
atOrInside: written,
|
|
209
|
-
aroundOnly: ascendingUnion(ancestors.map((a) => a.positions)).filter((i) => !already.has(i)),
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
exports.writerCandidates = writerCandidates;
|
|
213
|
-
/** The ascending, de-duplicated union of ascending position lists. */
|
|
214
|
-
function ascendingUnion(lists) {
|
|
215
|
-
if (lists.length === 0)
|
|
216
|
-
return [];
|
|
217
|
-
if (lists.length === 1)
|
|
218
|
-
return [...lists[0]];
|
|
219
|
-
const all = new Set();
|
|
220
|
-
for (const list of lists)
|
|
221
|
-
for (const i of list)
|
|
222
|
-
all.add(i);
|
|
223
|
-
return [...all].sort((a, b) => a - b);
|
|
224
|
-
}
|
|
225
|
-
exports.ascendingUnion = ascendingUnion;
|
|
226
|
-
/**
|
|
227
|
-
* Did this commit reach `key` ONLY through rows inside it — at least one row `'inside'` the key, and no
|
|
228
|
-
* row on it or around it? Such a write changed part of the key's value, not the whole: the one test
|
|
229
|
-
* behind every `'nested-rows'` code (a slice note, a causal edge's `basis`, `findLastWriterWithBasis`).
|
|
230
|
-
*/
|
|
231
|
-
function writesOnlyInside(bundle, key) {
|
|
232
|
-
let inside = false;
|
|
233
|
-
for (const t of bundle.trace) {
|
|
234
|
-
const r = relation(t.path, key);
|
|
235
|
-
if (r === 'exact' || r === 'around')
|
|
236
|
-
return false;
|
|
237
|
-
if (r === 'inside')
|
|
238
|
-
inside = true;
|
|
239
|
-
}
|
|
240
|
-
return inside;
|
|
241
|
-
}
|
|
242
|
-
exports.writesOnlyInside = writesOnlyInside;
|
|
243
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5UGF0aHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL21lbW9yeS9rZXlQYXRocy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXVDRzs7O0FBRUgseUNBQW1DO0FBR25DOzs7Ozs7R0FNRztBQUNVLFFBQUEsU0FBUyxHQUFHLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxDQUFDO0FBS3RDLE1BQU0sVUFBVSxHQUFHLGdCQUFLLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBRXZDOzs7OztHQUtHO0FBQ0gsU0FBZ0IsUUFBUSxDQUFDLE9BQWUsRUFBRSxHQUFXO0lBQ25ELElBQUksT0FBTyxLQUFLLEdBQUc7UUFBRSxPQUFPLE9BQU8sQ0FBQztJQUNwQyxJQUFJLE9BQU8sQ0FBQyxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ2hDLE9BQU8sT0FBTyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEtBQUssVUFBVSxJQUFJLE9BQU8sQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0lBQ3pHLENBQUM7SUFDRCxPQUFPLEdBQUcsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLFVBQVUsSUFBSSxHQUFHLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztBQUN6RyxDQUFDO0FBTkQsNEJBTUM7QUFFRCw0RUFBNEU7QUFDNUUsU0FBZ0IsTUFBTSxDQUFDLElBQVk7SUFDakMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxnQkFBSyxDQUFDLENBQUM7SUFDaEMsT0FBTyxHQUFHLEtBQUssQ0FBQyxD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b21taXQgbG9nIHRvdWNoIGEgc3RhdGUga2V5LiBPTkUgYW5zd2VyIChGMywgOS4zMy4wKS5cbiAqXG4gKiBXSFkgVEhJUyBGSUxFIEVYSVNUUy4gQSBrZXkgcXVlcnkgKGBjb21taXRWYWx1ZUF0YCwgYGZpbmRMYXN0V3JpdGVyYCwgYGNhdXNhbENoYWluYCwgdGhlIHNsaWNlXG4gKiBsYXllcikgYXNrcyBcIndoaWNoIHJvd3Mgd3JvdGUgYGtleWA/XCIuIEVhY2ggcmVhZGVyIHVzZWQgdG8gYW5zd2VyIHdpdGggaXRzIG93biBgcm93LnBhdGggPT09IGtleWAsXG4gKiBzbyBhIHJvdyB3cml0dGVuIElOU0lERSB0aGUga2V5IOKAlCBgY2Zn4pCfYmAsIHdoaWNoIGV2ZXJ5IHN1YmZsb3cgc2VlZCBvZiBhbiBvYmplY3QsIGV2ZXJ5XG4gKiBvdXRwdXRNYXBwZXIgbWVyZ2UtYmFjayBhbmQgZXZlcnkgZm9yayBjaGlsZCdzIG5hbWVzcGFjZSBwcm9kdWNlcyDigJQgd2FzIGludmlzaWJsZSB0byBhbGwgb2ZcbiAqIHRoZW0sIHdoaWxlIHRoZSBmb2xkIChgc3RhdGVBdGAsIHRoZSBsaXZlIGNvbW1pdCkgYXBwbGllZCBpdC4gVGhlIGZvbGQgc2FpZCBge2E6MSxiOjJ9YDsgdGhlIGtleVxuICogcXVlcmllcyBzYWlkIFwibmV2ZXIgd3JpdHRlblwiLiBFdmVyeSByZWFkZXIgbm93IGFza3MgaGVyZS5cbiAqXG4gKiBUSEUgUEFUSCBIQUxGICh0aGlzIGZpbGUsIEwwIOKAlCBpdCBpbXBvcnRzIG9ubHkgdGhlIHBhdGggY29kZWMgYW5kIHR5cGVzKTpcbiAqICAgLSB7QGxpbmsgcmVsYXRpb259IOKAlCBob3cgYSByb3cncyBwYXRoIHNpdHMgYWdhaW5zdCBhIGtleSdzIHBhdGguIEEgc2VnbWVudCBwcmVmaXggb24gdGhlXG4gKiAgICAgREVMSU0tam9pbmVkIHBhdGgsIHRoZSB3YXkgUkZDIDY5MDEgcHJlZml4ZXMgYSBKU09OIFBvaW50ZXI6IGBjZmdgIGlzIGEgcHJlZml4IG9mIGBjZmfikJ9hYCxcbiAqICAgICBuZXZlciBvZiBgY2ZnWGAuIEEgcm93IGlzIGAnZXhhY3QnYCAob24gdGhlIGtleSksIGAnaW5zaWRlJ2AgKGJlbG93IGl0IOKAlCBpdCB3cm90ZSBwYXJ0IG9mIHRoZVxuICogICAgIGtleSdzIHZhbHVlKSBvciBgJ2Fyb3VuZCdgIChhYm92ZSBpdCDigJQgaXQgd3JvdGUgYSBjb250YWluZXIgdGhhdCBob2xkcyB0aGUga2V5KS5cbiAqICAgLSB7QGxpbmsgYnVpbGRXcml0ZXJJbmRleH0gLyB7QGxpbmsgd3JpdGVyQ2FuZGlkYXRlc30g4oCUIG9uZSBwYXNzIG92ZXIgYSBsb2csIHRoZW4gdGhlIHJvd3MgdGhhdFxuICogICAgIGNhbiBoYXZlIHdyaXR0ZW4gYSBrZXksIGZvdW5kIHRocm91Z2ggaXRzIHRvcC1sZXZlbCBrZXkgaW5zdGVhZCBvZiBhIHNjYW4uXG4gKlxuICogVEhFIFJVTEVTIChkZWZpbmVkIGhlcmU7IHRoZSBmb2xkIGlzIEwxIGFuZCB0aGUgbG9nIHJlYWRlcnMgTDMsIHNvIGBjb21taXRMb2dVdGlscy50c2AgYXBwbGllc1xuICogdGhlbSDigJQgYHdyaXRlcnNPZmAsIGBmaW5kTGFzdFdyaXRlcmAsIGBjb21taXRWYWx1ZUF0YCk6XG4gKiAgIC0gVEhFIFdSSVRFUiBSVUxFIOKAlCBjb21taXQgYGNgIFdSSVRFUyBrZXkgYEtgIGlmZiBgY2AgaGFzIGEgcm93IGAnZXhhY3QnYCBvciBgJ2luc2lkZSdgIGBLYCxcbiAqICAgICBvciBhIHJvdyBgJ2Fyb3VuZCdgIGBLYCBhY3Jvc3Mgd2hpY2ggdGhlIHZhbHVlIGF0IGBLYCBkaWZmZXJzIChjb21wYXJlZCBvdmVyIHRoZSB3aG9sZSBjb21taXQsXG4gKiAgICAgbm90IHJvdyBieSByb3c6IGEgdmFsdWUgdGhhdCBjaGFuZ2VzIGFuZCBjaGFuZ2VzIGJhY2sgaW5zaWRlIG9uZSBjb21taXQgd2FzIG5vdCB3cml0dGVuKS5cbiAqICAgICBBIHRvcC1sZXZlbCBrZXkgaGFzIG5vIGAnYXJvdW5kJ2Agcm93cywgc28gZm9yIGl0IHRoZSBydWxlIGlzIHRoZSBwYXRoIGNoZWNrIGFsb25lLlxuICogICAgIFdoeSBub3QgZXZlcnkgYCdhcm91bmQnYCByb3c6IGAkdXBkYXRlKCdjZmcnLCB7IGxpc3Q6IFszXSB9KWAgaXMgYSBgbWVyZ2VgIHJvdyBvbiBgY2ZnYCwgYnV0XG4gKiAgICAgaXQgbmV2ZXIgcmVhY2hlcyBgY2Zn4pCfYWAg4oCUIGNvdW50aW5nIGl0IG5hbWVkIHRoZSB3cm9uZyB3cml0ZXIgb2YgYGNmZ+KQn2FgLlxuICogICAtIFRIRSBWQUxVRSBSVUxFIOKAlCB0aGUgdmFsdWUgb2YgYEtgIGF0IGNvbW1pdCBgaWAgaXMgdGhlIGZvbGQgb2YgRVZFUlkgcm93IHVuZGVyIGBLYCdzIHRvcC1sZXZlbFxuICogICAgIGtleSB1cCB0byBgaWAsIGFuY2hvcmVkIGF0IHRoYXQga2V5J3MgbGFzdCBgc2V0YC9gZGVsZXRlYCwgcmVhZCBhdCBgS2A6IHRoZSBmb2xkIGBzdGF0ZUF0YFxuICogICAgIGRvZXMsIHJlc3RyaWN0ZWQgdG8gb25lIHRvcC1sZXZlbCBrZXkuIFRvcC1sZXZlbCBrZXlzIG5ldmVyIGludGVyYWN0IHVuZGVyIHRoZSBzdGVwLCBzbyB0aGVcbiAqICAgICByZXN0cmljdGlvbiBpcyBleGFjdC4gRm9sZGluZyBvbmx5IHRoZSByb3dzIHRoYXQgdG91Y2ggYEtgIGlzIE5PVDogYW4gYXJyYXkgdW5pb25cbiAqICAgICAoYGRlZXBTbWFydE1lcmdlYCkgZGVkdXBzIHRoZSB3aG9sZSBhcnJheSwgc28gYSBzaWJsaW5nIGVsZW1lbnQgd3JpdHRlbiBiZXNpZGUgYGHikJ8xYCBjaGFuZ2VzXG4gKiAgICAgd2hlcmUgYSBsYXRlciBtZXJnZSBvbiBgYWAgbGVhdmVzIGBhWzFdYC5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogcmVsYXRpb24oJ2NmZ1xcdTAwMUZiJywgJ2NmZycpOyAvLyAnaW5zaWRlJyDigJQgdGhlIHJvdyB3cm90ZSBwYXJ0IG9mIGNmZ1xuICogcmVsYXRpb24oJ2NmZycsICdjZmdcXHUwMDFGYScpOyAvLyAnYXJvdW5kJyDigJQgdGhlIHJvdyB3cm90ZSB0aGUgY29udGFpbmVyIGNmZy5hIGxpdmVzIGluXG4gKiByZWxhdGlvbignY2ZnWCcsICdjZmcnKTsgICAgICAgLy8gdW5kZWZpbmVkIOKAlCBhIGRpZmZlcmVudCBrZXksIG5vdCBhIHByZWZpeCBtYXRjaFxuICogYGBgXG4gKi9cblxuaW1wb3J0IHsgREVMSU0gfSBmcm9tICcuL3BhdGhzLmpzJztcbmltcG9ydCB0eXBlIHsgQ29tbWl0QnVuZGxlIH0gZnJvbSAnLi90eXBlcy5qcyc7XG5cbi8qKlxuICogVGhlIFdPUksgZXZlcnkga2V5IHF1ZXJ5IGhhcyBkb25lIOKAlCByb3dzIGluZGV4ZWQgYW5kIHNjYW5uZWQsIGZvbGQgc3RlcHMsIGFyb3VuZC12ZXJkaWN0cywgdHJpZSBhbmRcbiAqIGFuY2VzdG9yIHN0ZXBzLCBiaW5hcnkgc2VhcmNoZXMsIGEgY2F1c2FsIHdhbGsncyBvd24gbG9vcHMg4oCUIHN1bW1lZCBhY3Jvc3MgY2FsbHMuIEEgZGV0ZXJtaW5pc3RpYyBjb3N0XG4gKiBtZWFzdXJlOiBgdGVzdC9saWIvbWVtb3J5L2JvdW5kYXJ5L2tleS1xdWVyeS1zY2FsaW5nLnRlc3QudHNgIGFzc2VydHMgYSBjYXVzYWwgd2FsaydzIHdvcmsgZ3Jvd3MgbGluZWFybHlcbiAqIGluIHRoZSBsb2cgYnkgQ09VTlRJTkcgaXQgKGEgd2FsbC1jbG9jayByYXRpbyBmYWlsZWQgb24gYSBidXN5IG1hY2hpbmUpLiBOZXZlciByZWFkIGJ5IHRoZSBsaWJyYXJ5OyBvbmVcbiAqIGludGVnZXIgYWRkIHBlciB1bml0IG9mIHdvcmsgaXQgYWxyZWFkeSBkb2VzLiBIZXJlLCBhdCBMMCwgc28gZXZlcnkgbGF5ZXIgdGhhdCBkb2VzIHRoYXQgd29yayBjYW4gY291bnQgaXQuXG4gKi9cbmV4cG9ydCBjb25zdCBxdWVyeVdvcmsgPSB7IHVuaXRzOiAwIH07XG5cbi8qKiBIb3cgYSByb3cncyBwYXRoIHNpdHMgYWdhaW5zdCBhIGtleSdzIHBhdGguIGB1bmRlZmluZWRgIGZyb20ge0BsaW5rIHJlbGF0aW9ufSBtZWFucyBkaXNqb2ludC4gKi9cbmV4cG9ydCB0eXBlIFBhdGhSZWxhdGlvbiA9ICdleGFjdCcgfCAnaW5zaWRlJyB8ICdhcm91bmQnO1xuXG5jb25zdCBERUxJTV9DT0RFID0gREVMSU0uY2hhckNvZGVBdCgwKTtcblxuLyoqXG4gKiBIb3cgdGhlIHJvdyBwYXRoIGByb3dQYXRoYCBzaXRzIGFnYWluc3QgdGhlIGtleSBga2V5YCDigJQgYm90aCBERUxJTS1qb2luZWQgYFRyYWNlRW50cnkucGF0aGBcbiAqIHN0cmluZ3MgKGEgdG9wLWxldmVsIGtleSBpcyBhIG9uZS1zZWdtZW50IHBhdGgpLiBgJ2V4YWN0J2Agd2hlbiB0aGV5IGFyZSBlcXVhbCwgYCdpbnNpZGUnYCB3aGVuXG4gKiB0aGUgcm93IGlzIGJlbG93IHRoZSBrZXksIGAnYXJvdW5kJ2Agd2hlbiB0aGUgcm93IGlzIGFib3ZlIGl0LCBgdW5kZWZpbmVkYCB3aGVuIG5laXRoZXIgaXMgYVxuICogc2VnbWVudCBwcmVmaXggb2YgdGhlIG90aGVyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVsYXRpb24ocm93UGF0aDogc3RyaW5nLCBrZXk6IHN0cmluZyk6IFBhdGhSZWxhdGlvbiB8IHVuZGVmaW5lZCB7XG4gIGlmIChyb3dQYXRoID09PSBrZXkpIHJldHVybiAnZXhhY3QnO1xuICBpZiAocm93UGF0aC5sZW5ndGggPiBrZXkubGVuZ3RoKSB7XG4gICAgcmV0dXJuIHJvd1BhdGguY2hhckNvZGVBdChrZXkubGVuZ3RoKSA9PT0gREVMSU1fQ09ERSAmJiByb3dQYXRoLnN0YXJ0c1dpdGgoa2V5KSA/ICdpbnNpZGUnIDogdW5kZWZpbmVkO1xuICB9XG4gIHJldHVybiBrZXkuY2hhckNvZGVBdChyb3dQYXRoLmxlbmd0aCkgPT09IERFTElNX0NPREUgJiYga2V5LnN0YXJ0c1dpdGgocm93UGF0aCkgPyAnYXJvdW5kJyA6IHVuZGVmaW5lZDtcbn1cblxuLyoqIFRoZSB0b3AtbGV2ZWwga2V5IGEgREVMSU0tam9pbmVkIHBhdGggYmVsb25ncyB0byDigJQgaXRzIGZpcnN0IHNlZ21lbnQuICovXG5leHBvcnQgZnVuY3Rpb24gcm9vdE9mKHBhdGg6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IGN1dCA9IHBhdGguaW5kZXhPZihERUxJTSk7XG4gIHJldHVybiBjdXQgPT09IC0xID8gcGF0aCA6IHBhdGguc2xpY2UoMCwgY3V0KTtcbn1cblxuLyoqXG4gKiBPbmUgd3JpdHRlbiBwYXRoIGluIGEge0BsaW5rIFdyaXRlckluZGV4fSDigJQgYSBub2RlIG9mIHRoZSBwYXRoIFRSSUUgYnVpbHQgb3ZlciBhIGxvZy4gQSBub2RlIGV4aXN0cyBmb3JcbiAqIGV2ZXJ5IHdyaXR0ZW4gcGF0aCBhbmQgZXZlcnkgcHJlZml4IG9mIG9uZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQYXRoTm9kZSB7XG4gIC8qKiBUaGUgREVMSU0tam9pbmVkIHBhdGggdGhpcyBub2RlIHN0YW5kcyBmb3IuICovXG4gIHJlYWRvbmx5IHBhdGg6IHN0cmluZztcbiAgLyoqIEFSUkFZIHBvc2l0aW9ucyBvZiB0aGUgY29tbWl0cyB3aXRoIGEgcm93IGV4YWN0bHkgb24gdGhpcyBwYXRoIOKAlCBhc2NlbmRpbmcsIG9uZSBwZXIgY29tbWl0LiAqL1xuICByZWFkb25seSBwb3NpdGlvbnM6IG51bWJlcltdO1xuICAvKiogVGhlIHN1YnNldCBvZiB7QGxpbmsgcG9zaXRpb25zfSB3aG9zZSByb3cgaGVyZSBpcyBhIGBzZXRgIG9yIGEgYGRlbGV0ZWAgKGl0IGRlY2lkZXMgdGhlIHZhbHVlIGFsb25lKS4gKi9cbiAgcmVhZG9ubHkgdG90YWxzOiBudW1iZXJbXTtcbiAgLyoqIFBvc2l0aW9ucyBvZiBjb21taXRzIHdob3NlIHJvdyB3aXRoIGEgbm9uLWBkZWxldGVgIHZlcmIgc2l0cyBvbiB0aGlzIHBhdGggKHRoZSByZXN0IGFyZSBkZWxldGVzIG9ubHkpLiAqL1xuICByZWFkb25seSB3cml0ZXM6IG51bWJlcltdO1xuICAvKiogVGhlIG5leHQgc2VnbWVudCDihpIgaXRzIG5vZGUuICovXG4gIHJlYWRvbmx5IGNoaWxkcmVuOiBNYXA8c3RyaW5nLCBQYXRoTm9kZT47XG4gIC8qKiBNZW1vIG9mIHtAbGluayBzdWJ0cmVlUG9zaXRpb25zfS4gKi9cbiAgc3VidHJlZT86IHJlYWRvbmx5IG51bWJlcltdO1xufVxuXG4vKipcbiAqIFRoZSBwb3NpdGlvbnMgaW4gYSBsb2cgd2hlcmUgZWFjaCB3cml0dGVuIHBhdGggd2FzIHdyaXR0ZW46IGEgcGF0aCB0cmllIHBlciB0b3AtbGV2ZWwga2V5LiBCdWlsdCBpbiBPTkVcbiAqIHBhc3MgKGBPKHRvdGFsIHBhdGggc2VnbWVudHMpYCk7IGEga2V5J3MgY2FuZGlkYXRlcyB0aGVuIGNvc3QgYE8oZGVwdGggKyBtYXRjaGVzKWAg4oCUIGl0cyBub2RlLCBpdHNcbiAqIGFuY2VzdG9ycywgaXRzIHN1YnRyZWUg4oCUIG5ldmVyIGEgc2NhbiBvZiBldmVyeSBwYXRoIHVuZGVyIGl0cyB0b3AtbGV2ZWwga2V5LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFdyaXRlckluZGV4IHtcbiAgLyoqIEV2ZXJ5IHRvcC1sZXZlbCBrZXkg4oaSIHRoZSByb290IG9mIGl0cyB0cmllLiAqL1xuICByZWFkb25seSByb290czogUmVhZG9ubHlNYXA8c3RyaW5nLCBQYXRoTm9kZT47XG59XG5cbmZ1bmN0aW9uIG5vZGVPZihwYXRoOiBzdHJpbmcpOiBQYXRoTm9kZSB7XG4gIHJldHVybiB7IHBhdGgsIHBvc2l0aW9uczogW10sIHRvdGFsczogW10sIHdyaXRlczogW10sIGNoaWxkcmVuOiBuZXcgTWFwKCkgfTtcbn1cblxuLyoqIEFwcGVuZCBgaWAgdG8gYW4gYXNjZW5kaW5nIGxpc3QgdW5sZXNzIGl0IGlzIGFscmVhZHkgaXRzIGxhc3QgZWxlbWVudC4gKi9cbmZ1bmN0aW9uIHB1c2hPbmNlKGxpc3Q6IG51bWJlcltdLCBpOiBudW1iZXIpOiB2b2lkIHtcbiAgaWYgKGxpc3RbbGlzdC5sZW5ndGggLSAxXSAhPT0gaSkgbGlzdC5wdXNoKGkpO1xufVxuXG4vKipcbiAqIE9uZSBwYXNzIG92ZXIgYGNvbW1pdExvZ2A6IHRoZSBwYXRoIHRyaWUgb2YgZXZlcnkgd3JpdHRlbiBwYXRoLiBCdWlsZCBpdCBPTkNFIHdoZW4gYSByZWFkZXIgYXNrcyBhYm91dFxuICogbWFueSBrZXlzIChhIGNhdXNhbCB3YWxrLCBhIGZvcndhcmQgc2xpY2UpIOKAlCBvciBsZXQgYGNvbW1pdExvZ1V0aWxzIMK3IGxvZ01vZGVsYCBtZW1vaXNlIGl0IGZvciBhIGZyb3plbiBsb2cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBidWlsZFdyaXRlckluZGV4KGNvbW1pdExvZzogcmVhZG9ubHkgQ29tbWl0QnVuZGxlW10pOiBXcml0ZXJJbmRleCB7XG4gIGNvbnN0IHJvb3RzID0gbmV3IE1hcDxzdHJpbmcsIFBhdGhOb2RlPigpO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGNvbW1pdExvZy5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IHRyYWNlID0gY29tbWl0TG9nW2ldLnRyYWNlO1xuICAgIGZvciAobGV0IHJvdyA9IDA7IHJvdyA8IHRyYWNlLmxlbmd0aDsgcm93KyspIHtcbiAgICAgIGNvbnN0IHsgcGF0aCwgdmVyYiB9ID0gdHJhY2Vbcm93XTtcbiAgICAgIGNvbnN0IHNlZ3MgPSBwYXRoLnNwbGl0KERFTElNKTtcbiAgICAgIGxldCBub2RlOiBQYXRoTm9kZSB8IHVuZGVmaW5lZCA9IHJvb3RzLmdldChzZWdzWzBdKTtcbiAgICAgIGlmIChub2RlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgbm9kZSA9IG5vZGVPZihzZWdzWzBdKTtcbiAgICAgICAgcm9vdHMuc2V0KHNlZ3NbMF0sIG5vZGUpO1xuICAgICAgfVxuICAgICAgZm9yIChsZXQgcyA9IDE7IHMgPCBzZWdzLmxlbmd0aDsgcysrKSB7XG4gICAgICAgIGxldCBjaGlsZDogUGF0aE5vZGUgfCB1bmRlZmluZWQgPSBub2RlLmNoaWxkcmVuLmdldChzZWdzW3NdKTtcbiAgICAgICAgaWYgKGNoaWxkID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBjaGlsZCA9IG5vZGVPZihub2RlLnBhdGggKyBERUxJTSArIHNlZ3Nbc10pO1xuICAgICAgICAgIG5vZGUuY2hpbGRyZW4uc2V0KHNlZ3Nbc10sIGNoaWxkKTtcbiAgICAgICAgfVxuICAgICAgICBub2RlID0gY2hpbGQ7XG4gICAgICB9XG4gICAgICBwdXNoT25jZShub2RlLnBvc2l0aW9ucywgaSk7XG4gICAgICBpZiAodmVyYiA9PT0gJ3NldCcgfHwgdmVyYiA9PT0gJ2RlbGV0ZScpIHB1c2hPbmNlKG5vZGUudG90YWxzLCBpKTtcbiAgICAgIGlmICh2ZXJiICE9PSAnZGVsZXRlJykgcHVzaE9uY2Uobm9kZS53cml0ZXMsIGkpO1xuICAgIH1cbiAgfVxuICByZXR1cm4geyByb290cyB9O1xufVxuXG4vKiogRXZlcnkgcGF0aCBhIHJvdyB3YXMgd3JpdHRlbiBvbiwgaW4gdHJpZSBvcmRlci4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXRoc1dyaXR0ZW4oaW5kZXg6IFdyaXRlckluZGV4KTogc3RyaW5nW10ge1xuICBjb25zdCBvdXQ6IHN0cmluZ1tdID0gW107XG4gIGNvbnN0IHN0YWNrID0gWy4uLmluZGV4LnJvb3RzLnZhbHVlcygpXTtcbiAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDApIHtcbiAgICBjb25zdCBub2RlID0gc3RhY2sucG9wKCkgYXMgUGF0aE5vZGU7XG4gICAgaWYgKG5vZGUucG9zaXRpb25zLmxlbmd0aCA+IDApIG91dC5wdXNoKG5vZGUucGF0aCk7XG4gICAgZm9yIChjb25zdCBjaGlsZCBvZiBub2RlLmNoaWxkcmVuLnZhbHVlcygpKSBzdGFjay5wdXNoKGNoaWxkKTtcbiAgfVxuICByZXR1cm4gb3V0O1xufVxuXG4vKiogVGhlIG5vZGUgZm9yIGBrZXlgLCBvciB1bmRlZmluZWQgd2hlbiBubyByb3cgd2FzIHdyaXR0ZW4gb24gaXQgb3IgYmVsb3cgaXQuICovXG5leHBvcnQgZnVuY3Rpb24gbm9kZUF0KGluZGV4OiBXcml0ZXJJbmRleCwga2V5OiBzdHJpbmcpOiBQYXRoTm9kZSB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IHNlZ3MgPSBrZXkuc3BsaXQoREVMSU0pO1xuICBxdWVyeVdvcmsudW5pdHMgKz0gc2Vncy5sZW5ndGg7XG4gIGxldCBub2RlID0gaW5kZXgucm9vdHMuZ2V0KHNlZ3NbMF0pO1xuICBmb3IgKGxldCBzID0gMTsgbm9kZSAhPT0gdW5kZWZpbmVkICYmIHMgPCBzZWdzLmxlbmd0aDsgcysrKSBub2RlID0gbm9kZS5jaGlsZHJlbi5nZXQoc2Vnc1tzXSk7XG4gIHJldHVybiBub2RlO1xufVxuXG4vKiogVGhlIG5vZGVzIG9mIGBrZXlgJ3MgUFJPUEVSIGFuY2VzdG9ycyB0aGF0IGV4aXN0IGluIHRoZSBpbmRleCwgdG9wLWxldmVsIGtleSBmaXJzdC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhbmNlc3Rvck5vZGVzKGluZGV4OiBXcml0ZXJJbmRleCwga2V5OiBzdHJpbmcpOiBQYXRoTm9kZVtdIHtcbiAgY29uc3Qgc2VncyA9IGtleS5zcGxpdChERUxJTSk7XG4gIGNvbnN0IG91dDogUGF0aE5vZGVbXSA9IFtdO1xuICBxdWVyeVdvcmsudW5pdHMgKz0gc2Vncy5sZW5ndGg7XG4gIGxldCBub2RlID0gaW5kZXgucm9vdHMuZ2V0KHNlZ3NbMF0pO1xuICBmb3IgKGxldCBzID0gMTsgbm9kZSAhPT0gdW5kZWZpbmVkICYmIHMgPCBzZWdzLmxlbmd0aDsgcysrKSB7XG4gICAgb3V0LnB1c2gobm9kZSk7XG4gICAgbm9kZSA9IG5vZGUuY2hpbGRyZW4uZ2V0KHNlZ3Nbc10pO1xuICB9XG4gIHJldHVybiBvdXQ7XG59XG5cbi8qKiBFdmVyeSBjb21taXQgd2l0aCBhIHJvdyBvbiBgbm9kZWAncyBwYXRoIG9yIGJlbG93IGl0IOKAlCBhc2NlbmRpbmcsIG1lbW9pc2VkIG9uIHRoZSBub2RlLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN1YnRyZWVQb3NpdGlvbnMobm9kZTogUGF0aE5vZGUpOiByZWFkb25seSBudW1iZXJbXSB7XG4gIHF1ZXJ5V29yay51bml0cyArPSAxO1xuICBpZiAobm9kZS5zdWJ0cmVlID09PSB1bmRlZmluZWQpIHtcbiAgICBpZiAobm9kZS5jaGlsZHJlbi5zaXplID09PSAwKSBub2RlLnN1YnRyZWUgPSBub2RlLnBvc2l0aW9ucztcbiAgICBlbHNlIHtcbiAgICAgIGNvbnN0IGxpc3RzOiAocmVhZG9ubHkgbnVtYmVyW10pW10gPSBbbm9kZS5wb3NpdGlvbnNdO1xuICAgICAgZm9yIChjb25zdCBjaGlsZCBvZiBub2RlLmNoaWxkcmVuLnZhbHVlcygpKSBsaXN0cy5wdXNoKHN1YnRyZWVQb3NpdGlvbnMoY2hpbGQpKTtcbiAgICAgIG5vZGUuc3VidHJlZSA9IGFzY2VuZGluZ1VuaW9uKGxpc3RzKTtcbiAgICAgIHF1ZXJ5V29yay51bml0cyArPSBub2RlLnN1YnRyZWUubGVuZ3RoO1xuICAgIH1cbiAgfVxuICByZXR1cm4gbm9kZS5zdWJ0cmVlO1xufVxuXG4vKiogVGhlIGZpcnN0IGluZGV4IGluIGFuIGFzY2VuZGluZyBsaXN0IGhvbGRpbmcgYSB2YWx1ZSA+PSBgdmFsdWVgLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxvd2VyQm91bmQoc29ydGVkOiByZWFkb25seSBudW1iZXJbXSwgdmFsdWU6IG51bWJlcik6IG51bWJlciB7XG4gIHF1ZXJ5V29yay51bml0cyArPSAxO1xuICBsZXQgbG8gPSAwO1xuICBsZXQgaGkgPSBzb3J0ZWQubGVuZ3RoO1xuICB3aGlsZSAobG8gPCBoaSkge1xuICAgIGNvbnN0IG1pZCA9IChsbyArIGhpKSA+Pj4gMTtcbiAgICBpZiAoc29ydGVkW21pZF0gPCB2YWx1ZSkgbG8gPSBtaWQgKyAxO1xuICAgIGVsc2UgaGkgPSBtaWQ7XG4gIH1cbiAgcmV0dXJuIGxvO1xufVxuXG4vKiogVGhlIGxhc3QgdmFsdWUgaW4gYW4gYXNjZW5kaW5nIGxpc3QgdGhhdCBpcyA8IGBiZWZvcmVgLCBvciAtMS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsYXN0QmVmb3JlKHNvcnRlZDogcmVhZG9ubHkgbnVtYmVyW10sIGJlZm9yZTogbnVtYmVyKTogbnVtYmVyIHtcbiAgY29uc3QgYXQgPSBsb3dlckJvdW5kKHNvcnRlZCwgYmVmb3JlKTtcbiAgcmV0dXJuIGF0ID4gMCA/IHNvcnRlZFthdCAtIDFdIDogLTE7XG59XG5cbi8qKiBUaGUgdmFsdWVzIG9mIGFuIGFzY2VuZGluZyBsaXN0IGluIHRoZSBPUEVOIHJhbmdlIChgYWZ0ZXJgLCBgYmVmb3JlYCkuICovXG5leHBvcnQgZnVuY3Rpb24gYmV0d2Vlbihzb3J0ZWQ6IHJlYWRvbmx5IG51bWJlcltdLCBhZnRlcjogbnVtYmVyLCBiZWZvcmU6IG51bWJlcik6IHJlYWRvbmx5IG51bWJlcltdIHtcbiAgY29uc3Qgb3V0ID0gc29ydGVkLnNsaWNlKGxvd2VyQm91bmQoc29ydGVkLCBhZnRlciArIDEpLCBsb3dlckJvdW5kKHNvcnRlZCwgYmVmb3JlKSk7XG4gIHF1ZXJ5V29yay51bml0cyArPSBvdXQubGVuZ3RoO1xuICByZXR1cm4gb3V0O1xufVxuXG4vKiogVGhlIGNvbW1pdHMgdGhhdCBjYW4gaGF2ZSB3cml0dGVuIGEga2V5LCBzcGxpdCBieSB3aGF0IHRoZSB3cml0ZXIgcnVsZSBzdGlsbCBoYXMgdG8gYXNrLiAqL1xuZXhwb3J0IGludGVyZmFjZSBXcml0ZXJDYW5kaWRhdGVzIHtcbiAgLyoqIENvbW1pdHMgd2l0aCBhIHJvdyBgJ2V4YWN0J2Agb3IgYCdpbnNpZGUnYCB0aGUga2V5IOKAlCB3cml0ZXJzIGJ5IHRoZSBwYXRoIGFsb25lLiBBc2NlbmRpbmcuICovXG4gIHJlYWRvbmx5IGF0T3JJbnNpZGU6IHJlYWRvbmx5IG51bWJlcltdO1xuICAvKiogQ29tbWl0cyB3aXRoIGEgcm93IGAnYXJvdW5kJ2AgdGhlIGtleSBhbmQgbm9uZSBhdCBvciBpbnNpZGUgaXQg4oCUIHdyaXRlcnMgb25seSBpZiB0aGUgdmFsdWUgYXQgdGhlIGtleSBjaGFuZ2VkLiBBc2NlbmRpbmcuICovXG4gIHJlYWRvbmx5IGFyb3VuZE9ubHk6IHJlYWRvbmx5IG51bWJlcltdO1xufVxuXG4vKiogVGhlIHBhdGggaGFsZiBvZiB0aGUgd3JpdGVyIHJ1bGUgb3ZlciBhbiBpbmRleDogZXZlcnkgY29tbWl0IHRoYXQgY2FuIGhhdmUgd3JpdHRlbiBga2V5YC4gYE8oZGVwdGggKyBtYXRjaGVzKWAuICovXG5leHBvcnQgZnVuY3Rpb24gd3JpdGVyQ2FuZGlkYXRlcyhpbmRleDogV3JpdGVySW5kZXgsIGtleTogc3RyaW5nKTogV3JpdGVyQ2FuZGlkYXRlcyB7XG4gIGNvbnN0IG5vZGUgPSBub2RlQXQoaW5kZXgsIGtleSk7XG4gIGNvbnN0IHdyaXR0ZW4gPSBub2RlID09PSB1bmRlZmluZWQgPyBbXSA6IHN1YnRyZWVQb3NpdGlvbnMobm9kZSk7XG4gIGNvbnN0IGFuY2VzdG9ycyA9IGFuY2VzdG9yTm9kZXMoaW5kZXgsIGtleSk7XG4gIGlmIChhbmNlc3RvcnMubGVuZ3RoID09PSAwKSByZXR1cm4geyBhdE9ySW5zaWRlOiB3cml0dGVuLCBhcm91bmRPbmx5OiBbXSB9O1xuICBjb25zdCBhbHJlYWR5ID0gbmV3IFNldCh3cml0dGVuKTtcbiAgcmV0dXJuIHtcbiAgICBhdE9ySW5zaWRlOiB3cml0dGVuLFxuICAgIGFyb3VuZE9ubHk6IGFzY2VuZGluZ1VuaW9uKGFuY2VzdG9ycy5tYXAoKGEpID0+IGEucG9zaXRpb25zKSkuZmlsdGVyKChpKSA9PiAhYWxyZWFkeS5oYXMoaSkpLFxuICB9O1xufVxuXG4vKiogVGhlIGFzY2VuZGluZywgZGUtZHVwbGljYXRlZCB1bmlvbiBvZiBhc2NlbmRpbmcgcG9zaXRpb24gbGlzdHMuICovXG5leHBvcnQgZnVuY3Rpb24gYXNjZW5kaW5nVW5pb24obGlzdHM6IHJlYWRvbmx5IChyZWFkb25seSBudW1iZXJbXSlbXSk6IG51bWJlcltdIHtcbiAgaWYgKGxpc3RzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIFtdO1xuICBpZiAobGlzdHMubGVuZ3RoID09PSAxKSByZXR1cm4gWy4uLmxpc3RzWzBdXTtcbiAgY29uc3QgYWxsID0gbmV3IFNldDxudW1iZXI+KCk7XG4gIGZvciAoY29uc3QgbGlzdCBvZiBsaXN0cykgZm9yIChjb25zdCBpIG9mIGxpc3QpIGFsbC5hZGQoaSk7XG4gIHJldHVybiBbLi4uYWxsXS5zb3J0KChhLCBiKSA9PiBhIC0gYik7XG59XG5cbi8qKlxuICogRGlkIHRoaXMgY29tbWl0IHJlYWNoIGBrZXlgIE9OTFkgdGhyb3VnaCByb3dzIGluc2lkZSBpdCDigJQgYXQgbGVhc3Qgb25lIHJvdyBgJ2luc2lkZSdgIHRoZSBrZXksIGFuZCBub1xuICogcm93IG9uIGl0IG9yIGFyb3VuZCBpdD8gU3VjaCBhIHdyaXRlIGNoYW5nZWQgcGFydCBvZiB0aGUga2V5J3MgdmFsdWUsIG5vdCB0aGUgd2hvbGU6IHRoZSBvbmUgdGVzdFxuICogYmVoaW5kIGV2ZXJ5IGAnbmVzdGVkLXJvd3MnYCBjb2RlIChhIHNsaWNlIG5vdGUsIGEgY2F1c2FsIGVkZ2UncyBgYmFzaXNgLCBgZmluZExhc3RXcml0ZXJXaXRoQmFzaXNgKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdyaXRlc09ubHlJbnNpZGUoYnVuZGxlOiBDb21taXRCdW5kbGUsIGtleTogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGxldCBpbnNpZGUgPSBmYWxzZTtcbiAgZm9yIChjb25zdCB0IG9mIGJ1bmRsZS50cmFjZSkge1xuICAgIGNvbnN0IHIgPSByZWxhdGlvbih0LnBhdGgsIGtleSk7XG4gICAgaWYgKHIgPT09ICdleGFjdCcgfHwgciA9PT0gJ2Fyb3VuZCcpIHJldHVybiBmYWxzZTtcbiAgICBpZiAociA9PT0gJ2luc2lkZScpIGluc2lkZSA9IHRydWU7XG4gIH1cbiAgcmV0dXJuIGluc2lkZTtcbn1cbiJdfQ==
|