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,360 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* timeTravel — a reader's cursor over a finished trace.
|
|
3
|
-
*
|
|
4
|
-
* The five laws this file implements (and the folder README states with an
|
|
5
|
-
* example each):
|
|
6
|
-
*
|
|
7
|
-
* 1. ONE cursor. This object holds the only position. `drill()` returns a
|
|
8
|
-
* separate cursor over a separate log, never a second position here.
|
|
9
|
-
* 2. A miss never moves. Every refusal returns the reason and leaves the
|
|
10
|
-
* cursor exactly where it was.
|
|
11
|
-
* 3. A fold result is detached. `stateAt` returns frozen, cloned state that
|
|
12
|
-
* shares nothing with the engine.
|
|
13
|
-
* 4. Marks live beside the log. They are the reader's notes, never written
|
|
14
|
-
* into the run's record.
|
|
15
|
-
* 5. Stops are DERIVED from the recorded log — read-time queries over
|
|
16
|
-
* collected data, never a re-walk that invents what was not recorded.
|
|
17
|
-
*
|
|
18
|
-
* A CHAIN (9.18.0) does not add a sixth law and does not bend these five: it
|
|
19
|
-
* is still one cursor, over sources that are still only read. What it adds is
|
|
20
|
-
* that the STEPS run across a pause/resume — see `chain.ts` for the ordering
|
|
21
|
-
* and lineage checks, and for why commit indices stay run-local.
|
|
22
|
-
*/
|
|
23
|
-
import { executionIndexOf, isExecutionKey, stageIdOf } from '../ids/runtimeStageId.js';
|
|
24
|
-
import { isPlainish, readTree } from './bundles.js';
|
|
25
|
-
import { refuseChain } from './chain.js';
|
|
26
|
-
import { commitStopsStrategy } from './commitStops.js';
|
|
27
|
-
import { foldLegsFrom, readSource } from './stateAt.js';
|
|
28
|
-
class Cursor {
|
|
29
|
-
stops;
|
|
30
|
-
path;
|
|
31
|
-
mountRuntimeStageId;
|
|
32
|
-
parent;
|
|
33
|
-
sourceCount;
|
|
34
|
-
legs;
|
|
35
|
-
sources;
|
|
36
|
-
options;
|
|
37
|
-
_marks;
|
|
38
|
-
step;
|
|
39
|
-
/** The last fold's working copy, so a step forward applies one bundle (9.25.0). */
|
|
40
|
-
foldMemo;
|
|
41
|
-
constructor(sources, options, path, parent, mountRuntimeStageId) {
|
|
42
|
-
this.sources = sources;
|
|
43
|
-
this.options = options;
|
|
44
|
-
this.path = path;
|
|
45
|
-
this.parent = parent;
|
|
46
|
-
this.mountRuntimeStageId = mountRuntimeStageId;
|
|
47
|
-
this.legs = sources.map((source) => readSource(source));
|
|
48
|
-
this.sourceCount = sources.length;
|
|
49
|
-
// The shipped strategy has no vocabulary of its own (`meta` is never set),
|
|
50
|
-
// so it serves any `TMeta` a caller asked for.
|
|
51
|
-
const strategy = options.strategy ?? commitStopsStrategy;
|
|
52
|
-
// ONE CALL PER SOURCE, with that source's own log and tree: a strategy
|
|
53
|
-
// never has to know it is part of a chain, and its indices stay local to
|
|
54
|
-
// the leg it was handed.
|
|
55
|
-
const perSource = this.legs.map((leg, i) => strategy.stopsFor(leg.log, readTree(sources[i].executionTree), sources[i].subflowResults));
|
|
56
|
-
this.stops = Object.freeze(sources.length === 1 ? perSource[0] : chainStops(perSource));
|
|
57
|
-
this._marks = [...(options.marks ?? [])];
|
|
58
|
-
this.step = 0;
|
|
59
|
-
}
|
|
60
|
-
// ── Position ─────────────────────────────────────────────────────────────
|
|
61
|
-
at() {
|
|
62
|
-
return this.stops[this.step];
|
|
63
|
-
}
|
|
64
|
-
moveTo(step) {
|
|
65
|
-
const from = this.at();
|
|
66
|
-
this.step = step;
|
|
67
|
-
return { moved: true, from, to: this.stops[step] };
|
|
68
|
-
}
|
|
69
|
-
/** Law 2: a refusal never touches `this.step`. */
|
|
70
|
-
refuse(reason, nearest) {
|
|
71
|
-
const at = this.at();
|
|
72
|
-
return nearest ? { moved: false, reason, at, nearest } : { moved: false, reason, at };
|
|
73
|
-
}
|
|
74
|
-
first() {
|
|
75
|
-
if (this.stops.length === 0)
|
|
76
|
-
return this.refuse('empty');
|
|
77
|
-
if (this.step === 0)
|
|
78
|
-
return this.refuse('clamped');
|
|
79
|
-
return this.moveTo(0);
|
|
80
|
-
}
|
|
81
|
-
last() {
|
|
82
|
-
if (this.stops.length === 0)
|
|
83
|
-
return this.refuse('empty');
|
|
84
|
-
const end = this.stops.length - 1;
|
|
85
|
-
if (this.step === end)
|
|
86
|
-
return this.refuse('clamped');
|
|
87
|
-
return this.moveTo(end);
|
|
88
|
-
}
|
|
89
|
-
prev() {
|
|
90
|
-
if (this.stops.length === 0)
|
|
91
|
-
return this.refuse('empty');
|
|
92
|
-
if (this.step === 0)
|
|
93
|
-
return this.refuse('clamped');
|
|
94
|
-
return this.moveTo(this.step - 1);
|
|
95
|
-
}
|
|
96
|
-
next() {
|
|
97
|
-
if (this.stops.length === 0)
|
|
98
|
-
return this.refuse('empty');
|
|
99
|
-
if (this.step >= this.stops.length - 1)
|
|
100
|
-
return this.refuse('clamped');
|
|
101
|
-
return this.moveTo(this.step + 1);
|
|
102
|
-
}
|
|
103
|
-
jumpTo(target) {
|
|
104
|
-
if (this.stops.length === 0)
|
|
105
|
-
return this.refuse('empty');
|
|
106
|
-
if (typeof target === 'number') {
|
|
107
|
-
const step = Math.trunc(target);
|
|
108
|
-
if (Number.isNaN(step))
|
|
109
|
-
return this.refuse('miss');
|
|
110
|
-
if (step < 0)
|
|
111
|
-
return this.refuse('clamped', this.stops[0]);
|
|
112
|
-
if (step > this.stops.length - 1)
|
|
113
|
-
return this.refuse('clamped', this.stops[this.stops.length - 1]);
|
|
114
|
-
if (step === this.step)
|
|
115
|
-
return this.refuse('clamped');
|
|
116
|
-
return this.moveTo(step);
|
|
117
|
-
}
|
|
118
|
-
// `''` is not an address: it is what the bookends and any pre-stage
|
|
119
|
-
// root commit carry. Those are reached by step, never by id.
|
|
120
|
-
if (target === '')
|
|
121
|
-
return this.refuse('miss');
|
|
122
|
-
const hit = this.stops.find((stop) => stop.runtimeStageId === target);
|
|
123
|
-
if (!hit)
|
|
124
|
-
return this.refuse('miss', this.nearestTo(target));
|
|
125
|
-
if (hit.step === this.step)
|
|
126
|
-
return this.refuse('clamped');
|
|
127
|
-
return this.moveTo(hit.step);
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* The closest namable stop for a `runtimeStageId` that is not on this axis:
|
|
131
|
-
* the last stop of the same STAGE (a different iteration of the same node),
|
|
132
|
-
* else the last stop whose commit precedes the missed id's execution index.
|
|
133
|
-
* Naming a neighbour is a courtesy for the UI — it never moves the cursor.
|
|
134
|
-
*/
|
|
135
|
-
nearestTo(runtimeStageId) {
|
|
136
|
-
if (!isExecutionKey(runtimeStageId))
|
|
137
|
-
return undefined;
|
|
138
|
-
const stagePart = stageIdOf(runtimeStageId);
|
|
139
|
-
const wanted = executionIndexOf(runtimeStageId);
|
|
140
|
-
let sameStage;
|
|
141
|
-
let byIndex;
|
|
142
|
-
for (const stop of this.stops) {
|
|
143
|
-
if (!isExecutionKey(stop.runtimeStageId))
|
|
144
|
-
continue;
|
|
145
|
-
if (stageIdOf(stop.runtimeStageId) === stagePart)
|
|
146
|
-
sameStage = stop;
|
|
147
|
-
if (!Number.isNaN(wanted)) {
|
|
148
|
-
const idx = executionIndexOf(stop.runtimeStageId);
|
|
149
|
-
if (!Number.isNaN(idx) && idx <= wanted)
|
|
150
|
-
byIndex = stop;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
return sameStage ?? byIndex;
|
|
154
|
-
}
|
|
155
|
-
// ── Reading ──────────────────────────────────────────────────────────────
|
|
156
|
-
stateAt(stop) {
|
|
157
|
-
const target = stop ?? this.at();
|
|
158
|
-
const leg = target?.sourceIdx ?? 0;
|
|
159
|
-
const fold = foldLegsFrom(this.legs, leg, target ? target.lastCommitIdx : -1, this.foldMemo);
|
|
160
|
-
this.foldMemo = fold.memo;
|
|
161
|
-
const folded = fold.folded;
|
|
162
|
-
// Which leg the index belongs to, but only when there is more than one —
|
|
163
|
-
// a single-source fold keeps the 9.17.0 shape exactly.
|
|
164
|
-
return this.legs.length > 1 ? { ...folded, sourceIdx: leg } : folded;
|
|
165
|
-
}
|
|
166
|
-
changedSince(from) {
|
|
167
|
-
const to = this.at();
|
|
168
|
-
if (!to)
|
|
169
|
-
return Object.freeze([]);
|
|
170
|
-
const start = from ?? this.stops[this.step - 1];
|
|
171
|
-
// No earlier stop (we are at `'start'`) ⇒ everything up to here: nothing
|
|
172
|
-
// on a run cursor, and the subflow's `inputMapper` seed on a drilled one
|
|
173
|
-
// (the start bookend covers the seed that precedes stage one — `commitStops`).
|
|
174
|
-
const toLeg = to.sourceIdx ?? 0;
|
|
175
|
-
const fromLeg = start ? start.sourceIdx ?? 0 : toLeg;
|
|
176
|
-
const afterIdx = start ? start.lastCommitIdx : -1;
|
|
177
|
-
const keys = new Set();
|
|
178
|
-
// A range that crosses a chain seam is walked leg by leg: the tail of the
|
|
179
|
-
// leg it started in, every leg in between whole, then the head of the leg
|
|
180
|
-
// it ends in. Backwards ranges walk nothing and give `[]`, as before.
|
|
181
|
-
for (let leg = fromLeg; leg <= toLeg && leg < this.legs.length; leg++) {
|
|
182
|
-
const log = this.legs[leg].log;
|
|
183
|
-
const lo = leg === fromLeg ? afterIdx + 1 : 0;
|
|
184
|
-
const hi = leg === toLeg ? to.lastCommitIdx : log.length - 1;
|
|
185
|
-
for (let i = lo; i <= hi; i++) {
|
|
186
|
-
const bundle = log[i];
|
|
187
|
-
if (!bundle)
|
|
188
|
-
continue;
|
|
189
|
-
for (const entry of bundle.trace)
|
|
190
|
-
keys.add(entry.path);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
return Object.freeze([...keys].sort());
|
|
194
|
-
}
|
|
195
|
-
// ── Marks (law 4: beside the log, never in it) ───────────────────────────
|
|
196
|
-
mark(name, stop) {
|
|
197
|
-
const target = stop ?? this.at();
|
|
198
|
-
if (!target)
|
|
199
|
-
return undefined;
|
|
200
|
-
const entry = Object.freeze({ name, runtimeStageId: target.runtimeStageId, step: target.step });
|
|
201
|
-
const existing = this._marks.findIndex((m) => m.name === name);
|
|
202
|
-
if (existing >= 0)
|
|
203
|
-
this._marks[existing] = entry;
|
|
204
|
-
else
|
|
205
|
-
this._marks.push(entry);
|
|
206
|
-
return entry;
|
|
207
|
-
}
|
|
208
|
-
marks() {
|
|
209
|
-
return Object.freeze([...this._marks]);
|
|
210
|
-
}
|
|
211
|
-
jumpToMark(name) {
|
|
212
|
-
if (this.stops.length === 0)
|
|
213
|
-
return this.refuse('empty');
|
|
214
|
-
const entry = this._marks.find((m) => m.name === name);
|
|
215
|
-
if (!entry)
|
|
216
|
-
return this.refuse('miss');
|
|
217
|
-
// Resolve by runtimeStageId first — the address that survives a change of
|
|
218
|
-
// strategy — and fall back to the remembered step only for the bookends,
|
|
219
|
-
// which have no stage id of their own.
|
|
220
|
-
const byId = entry.runtimeStageId
|
|
221
|
-
? this.stops.find((stop) => stop.runtimeStageId === entry.runtimeStageId)
|
|
222
|
-
: this.stops[entry.step];
|
|
223
|
-
if (!byId)
|
|
224
|
-
return this.refuse('miss', this.nearestTo(entry.runtimeStageId));
|
|
225
|
-
if (byId.step === this.step)
|
|
226
|
-
return this.refuse('clamped');
|
|
227
|
-
return this.moveTo(byId.step);
|
|
228
|
-
}
|
|
229
|
-
// ── Drilling (law 1: a separate cursor, not a second position) ───────────
|
|
230
|
-
drill(mountRuntimeStageId) {
|
|
231
|
-
// On a chain, the mount is looked for in every leg — a subflow that ran
|
|
232
|
-
// before the pause is in the first snapshot's results, one that ran after
|
|
233
|
-
// is in the second's. Ids are unique across a sound chain (chain.ts
|
|
234
|
-
// refuses one where they are not), so the first hit is the only hit.
|
|
235
|
-
let results;
|
|
236
|
-
let result;
|
|
237
|
-
for (const source of this.sources) {
|
|
238
|
-
// A stored recording's results are parsed JSON: read them as a map only
|
|
239
|
-
// when they are one, and as "no subflows" otherwise.
|
|
240
|
-
if (!isPlainish(source.subflowResults))
|
|
241
|
-
continue;
|
|
242
|
-
const hit = source.subflowResults[mountRuntimeStageId];
|
|
243
|
-
if (hit) {
|
|
244
|
-
results = source.subflowResults;
|
|
245
|
-
result = hit;
|
|
246
|
-
break;
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
const tree = result?.treeContext;
|
|
250
|
-
if (!results || !result || !tree || !Array.isArray(tree.history))
|
|
251
|
-
return undefined;
|
|
252
|
-
// `path` is the subflow PATH — the same string for every iteration of a
|
|
253
|
-
// mount inside a loop. `mountRuntimeStageId` is the iteration actually
|
|
254
|
-
// opened, so a UI can label and key three drill panels over `sfx#2`,
|
|
255
|
-
// `sfx#8`, `sfx#14` apart instead of calling all three 'sfx'.
|
|
256
|
-
const childPath = result.subflowId ?? mountRuntimeStageId;
|
|
257
|
-
const child = {
|
|
258
|
-
// Rows are narrowed per bundle when the child reads them — a stored
|
|
259
|
-
// recording's inner history needs no cast either.
|
|
260
|
-
commitLog: tree.history,
|
|
261
|
-
initialState: tree.initialState,
|
|
262
|
-
executionTree: tree.stageContexts,
|
|
263
|
-
// Nested subflow results are merged UP into one flat, dual-keyed map, so
|
|
264
|
-
// the child can drill further through the same map.
|
|
265
|
-
subflowResults: results,
|
|
266
|
-
};
|
|
267
|
-
return new Cursor([child], { strategy: this.options.strategy }, childPath, this, mountRuntimeStageId);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
/**
|
|
271
|
-
* Re-step per-source stops into ONE axis.
|
|
272
|
-
*
|
|
273
|
-
* The INTERIOR bookends go: a `'start'` on any leg but the first, and an
|
|
274
|
-
* `'end'` on any leg but the last, are bookends of a leg and not of the run —
|
|
275
|
-
* keeping them would put "the run is over" in the middle of the axis. The
|
|
276
|
-
* commits they covered are not orphaned: a fold always replays its leg from
|
|
277
|
-
* that leg's own base, and `changedSince` walks a seam-crossing range leg by
|
|
278
|
-
* leg (including the head of the leg it ends in). The stops' `commitIdx` /
|
|
279
|
-
* `lastCommitIdx` ranges PARTITION EACH LEG, never span the seam: a stop's
|
|
280
|
-
* range ends at its own leg's last index, and the next leg's first stop opens
|
|
281
|
-
* at that leg's 0.
|
|
282
|
-
*/
|
|
283
|
-
function chainStops(perSource) {
|
|
284
|
-
// "Interior" is measured against the legs that actually CONTRIBUTE stops: a
|
|
285
|
-
// leg whose log was empty has no bookends to drop and must not make its
|
|
286
|
-
// neighbour's `'start'` or `'end'` interior — the chained axis still opens
|
|
287
|
-
// with the first stop that exists and closes with the last.
|
|
288
|
-
const contributing = perSource.map((stops) => stops.length > 0);
|
|
289
|
-
const firstLeg = contributing.indexOf(true);
|
|
290
|
-
const lastLeg = contributing.lastIndexOf(true);
|
|
291
|
-
const out = [];
|
|
292
|
-
for (const [sourceIdx, stops] of perSource.entries()) {
|
|
293
|
-
for (const stop of stops) {
|
|
294
|
-
if (sourceIdx > firstLeg && stop.kind === 'start')
|
|
295
|
-
continue;
|
|
296
|
-
if (sourceIdx < lastLeg && stop.kind === 'end')
|
|
297
|
-
continue;
|
|
298
|
-
out.push({ ...stop, step: out.length, sourceIdx });
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
return out;
|
|
302
|
-
}
|
|
303
|
-
/**
|
|
304
|
-
* Open a reader's cursor over a finished run.
|
|
305
|
-
*
|
|
306
|
-
* Nothing here executes anything: `snapshot` is a record of a run that already
|
|
307
|
-
* happened, and every question is answered by reading it. A stored JSON
|
|
308
|
-
* snapshot works exactly like a live one — since 9.18.0 its `commitLog` may be
|
|
309
|
-
* an unvalidated `unknown[]`, narrowed per bundle where the fold reads it, so
|
|
310
|
-
* a replayed recording needs no cast.
|
|
311
|
-
*
|
|
312
|
-
* @param snapshot `executor.getSnapshot()`, or any object with the same
|
|
313
|
-
* shape — including one round-tripped through JSON, or a subflow subtree
|
|
314
|
-
* (`getSubtreeSnapshot()`, whose log is spelled `history`). An ARRAY of them
|
|
315
|
-
* is a CHAIN: a pause and its resume read as one axis (see below).
|
|
316
|
-
* @param options `strategy` chooses how stops are derived (default:
|
|
317
|
-
* `commitStops`, one stop per executed stage); `marks` seeds the cursor with
|
|
318
|
-
* bookmarks, e.g. restored from a saved reading session.
|
|
319
|
-
*
|
|
320
|
-
* @throws when a chain is not in run order, or its legs are not from one
|
|
321
|
-
* lineage — three checks, each with its own reason (see `chain.ts`):
|
|
322
|
-
* no `runtimeStageId` may appear in two legs; each leg's first execution
|
|
323
|
-
* index must be past the previous leg's last (the engine never resets the
|
|
324
|
-
* counter across a resume); and each leg's `initialState` must deep-equal
|
|
325
|
-
* the state the legs before it fold to — on a resume that base IS the state
|
|
326
|
-
* at the pause, so a foreign leg whose indices merely happen to be higher
|
|
327
|
-
* is refused too. The third check runs only where the record allows it: the
|
|
328
|
-
* later leg must carry an `initialState` and the earlier legs must fold from
|
|
329
|
-
* a real base with no unreadable rows; otherwise (an older recording with
|
|
330
|
-
* no base) the chain rests on the two index checks alone, and the fold's
|
|
331
|
-
* `basis` says what it stood on.
|
|
332
|
-
*
|
|
333
|
-
* @example
|
|
334
|
-
* ```typescript
|
|
335
|
-
* const tt = timeTravel(executor.getSnapshot());
|
|
336
|
-
* tt.jumpTo('score-risk#4');
|
|
337
|
-
* console.log(tt.changedSince()); // ['riskScore', 'tier']
|
|
338
|
-
* console.log(tt.stateAt().state); // state as that stage left it
|
|
339
|
-
* tt.mark('the bad one');
|
|
340
|
-
* const inner = tt.drill('sf-payment#7'); // a separate cursor, its own log
|
|
341
|
-
*
|
|
342
|
-
* // A pause and its resume, read as ONE axis:
|
|
343
|
-
* const chained = timeTravel([pausedSnapshot, resumedSnapshot]);
|
|
344
|
-
* chained.last(); // the run's real end
|
|
345
|
-
* chained.at()!.sourceIdx; // 1 — which leg the indices are in
|
|
346
|
-
* chained.jumpTo('approve#3'); // finds it in either leg
|
|
347
|
-
* ```
|
|
348
|
-
*/
|
|
349
|
-
export function timeTravel(snapshot, options = {}) {
|
|
350
|
-
const sources = Array.isArray(snapshot) ? snapshot : [snapshot];
|
|
351
|
-
// A one-element array is not a chain: it is the plain cursor, and skips the
|
|
352
|
-
// lineage checks a single source cannot fail.
|
|
353
|
-
if (sources.length !== 1) {
|
|
354
|
-
const refusal = refuseChain(sources.map((source) => readSource(source)));
|
|
355
|
-
if (refusal)
|
|
356
|
-
throw new Error(refusal);
|
|
357
|
-
}
|
|
358
|
-
return new Cursor(sources, options);
|
|
359
|
-
}
|
|
360
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGltZVRyYXZlbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvdGltZS10cmF2ZWwvdGltZVRyYXZlbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBcUJHO0FBRUgsT0FBTyxFQUFFLGdCQUFnQixFQUFFLGNBQWMsRUFBRSxTQUFTLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUN2RixPQUFPLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUNwRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ3ZELE9BQU8sRUFBa0MsWUFBWSxFQUFFLFVBQVUsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQXNCeEYsTUFBTSxNQUFNO0lBQ0QsS0FBSyxDQUF5QjtJQUM5QixJQUFJLENBQXFCO0lBQ3pCLG1CQUFtQixDQUFxQjtJQUN4QyxNQUFNLENBQWdDO0lBQ3RDLFdBQVcsQ0FBUztJQUVaLElBQUksQ0FBd0I7SUFDNUIsT0FBTyxDQUE4QjtJQUNyQyxPQUFPLENBQTJCO0lBQ2xDLE1BQU0sQ0FBUztJQUN4QixJQUFJLENBQVM7SUFDckIsbUZBQW1GO0lBQzNFLFFBQVEsQ0FBdUI7SUFFdkMsWUFDRSxPQUFvQyxFQUNwQyxPQUFpQyxFQUNqQyxJQUFhLEVBQ2IsTUFBMEIsRUFDMUIsbUJBQTRCO1FBRTVCLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ2pCLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1FBQ3JCLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxtQkFBbUIsQ0FBQztRQUMvQyxJQUFJLENBQUMsSUFB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b3Igb3ZlciBhIGZpbmlzaGVkIHRyYWNlLlxuICpcbiAqIFRoZSBmaXZlIGxhd3MgdGhpcyBmaWxlIGltcGxlbWVudHMgKGFuZCB0aGUgZm9sZGVyIFJFQURNRSBzdGF0ZXMgd2l0aCBhblxuICogZXhhbXBsZSBlYWNoKTpcbiAqXG4gKiAgIDEuIE9ORSBjdXJzb3IuIFRoaXMgb2JqZWN0IGhvbGRzIHRoZSBvbmx5IHBvc2l0aW9uLiBgZHJpbGwoKWAgcmV0dXJucyBhXG4gKiAgICAgIHNlcGFyYXRlIGN1cnNvciBvdmVyIGEgc2VwYXJhdGUgbG9nLCBuZXZlciBhIHNlY29uZCBwb3NpdGlvbiBoZXJlLlxuICogICAyLiBBIG1pc3MgbmV2ZXIgbW92ZXMuIEV2ZXJ5IHJlZnVzYWwgcmV0dXJucyB0aGUgcmVhc29uIGFuZCBsZWF2ZXMgdGhlXG4gKiAgICAgIGN1cnNvciBleGFjdGx5IHdoZXJlIGl0IHdhcy5cbiAqICAgMy4gQSBmb2xkIHJlc3VsdCBpcyBkZXRhY2hlZC4gYHN0YXRlQXRgIHJldHVybnMgZnJvemVuLCBjbG9uZWQgc3RhdGUgdGhhdFxuICogICAgICBzaGFyZXMgbm90aGluZyB3aXRoIHRoZSBlbmdpbmUuXG4gKiAgIDQuIE1hcmtzIGxpdmUgYmVzaWRlIHRoZSBsb2cuIFRoZXkgYXJlIHRoZSByZWFkZXIncyBub3RlcywgbmV2ZXIgd3JpdHRlblxuICogICAgICBpbnRvIHRoZSBydW4ncyByZWNvcmQuXG4gKiAgIDUuIFN0b3BzIGFyZSBERVJJVkVEIGZyb20gdGhlIHJlY29yZGVkIGxvZyDigJQgcmVhZC10aW1lIHF1ZXJpZXMgb3ZlclxuICogICAgICBjb2xsZWN0ZWQgZGF0YSwgbmV2ZXIgYSByZS13YWxrIHRoYXQgaW52ZW50cyB3aGF0IHdhcyBub3QgcmVjb3JkZWQuXG4gKlxuICogQSBDSEFJTiAoOS4xOC4wKSBkb2VzIG5vdCBhZGQgYSBzaXh0aCBsYXcgYW5kIGRvZXMgbm90IGJlbmQgdGhlc2UgZml2ZTogaXRcbiAqIGlzIHN0aWxsIG9uZSBjdXJzb3IsIG92ZXIgc291cmNlcyB0aGF0IGFyZSBzdGlsbCBvbmx5IHJlYWQuIFdoYXQgaXQgYWRkcyBpc1xuICogdGhhdCB0aGUgU1RFUFMgcnVuIGFjcm9zcyBhIHBhdXNlL3Jlc3VtZSDigJQgc2VlIGBjaGFpbi50c2AgZm9yIHRoZSBvcmRlcmluZ1xuICogYW5kIGxpbmVhZ2UgY2hlY2tzLCBhbmQgZm9yIHdoeSBjb21taXQgaW5kaWNlcyBzdGF5IHJ1bi1sb2NhbC5cbiAqL1xuXG5pbXBvcnQgeyBleGVjdXRpb25JbmRleE9mLCBpc0V4ZWN1dGlvbktleSwgc3RhZ2VJZE9mIH0gZnJvbSAnLi4vaWRzL3J1bnRpbWVTdGFnZUlkLmpzJztcbmltcG9ydCB7IGlzUGxhaW5pc2gsIHJlYWRUcmVlIH0gZnJvbSAnLi9idW5kbGVzLmpzJztcbmltcG9ydCB7IHJlZnVzZUNoYWluIH0gZnJvbSAnLi9jaGFpbi5qcyc7XG5pbXBvcnQgeyBjb21taXRTdG9wc1N0cmF0ZWd5IH0gZnJvbSAnLi9jb21taXRTdG9wcy5qcyc7XG5pbXBvcnQgeyB0eXBlIEZvbGRNZW1vLCB0eXBlIFJlYWRTb3VyY2UsIGZvbGRMZWdzRnJvbSwgcmVhZFNvdXJjZSB9IGZyb20gJy4vc3RhdGVBdC5qcyc7XG5pbXBvcnQgdHlwZSB7XG4gIEZvbGRlZFN0YXRlLFxuICBNYXJrLFxuICBNb3ZlLFxuICBTdG9wLFxuICBUaW1lVHJhdmVsLFxuICBUaW1lVHJhdmVsT3B0aW9ucyxcbiAgVGltZVRyYXZlbFNvdXJjZSxcbiAgVGltZVRyYXZlbFN0cmF0ZWd5LFxufSBmcm9tICcuL3R5cGVzLmpzJztcblxuLyoqIEEgc3ViZmxvdyByZXN1bHQgYXMgdGhpcyBtb2R1bGUgbmVlZHMgdG8gcmVhZCBpdCDigJQgZHVjay10eXBlZCBvbiBwdXJwb3NlLiAqL1xuaW50ZXJmYWNlIFN1YmZsb3dSZXN1bHRTaGFwZSB7XG4gIHN1YmZsb3dJZD86IHN0cmluZztcbiAgdHJlZUNvbnRleHQ/OiB7XG4gICAgaGlzdG9yeT86IHVua25vd25bXTtcbiAgICBpbml0aWFsU3RhdGU/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICBzdGFnZUNvbnRleHRzPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIH07XG59XG5cbmNsYXNzIEN1cnNvcjxUTWV0YT4gaW1wbGVtZW50cyBUaW1lVHJhdmVsPFRNZXRhPiB7XG4gIHJlYWRvbmx5IHN0b3BzOiByZWFkb25seSBTdG9wPFRNZXRhPltdO1xuICByZWFkb25seSBwYXRoOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIHJlYWRvbmx5IG1vdW50UnVudGltZVN0YWdlSWQ6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgcmVhZG9ubHkgcGFyZW50OiBUaW1lVHJhdmVsPFRNZXRhPiB8IHVuZGVmaW5lZDtcbiAgcmVhZG9ubHkgc291cmNlQ291bnQ6IG51bWJlcjtcblxuICBwcml2YXRlIHJlYWRvbmx5IGxlZ3M6IHJlYWRvbmx5IFJlYWRTb3VyY2VbXTtcbiAgcHJpdmF0ZSByZWFkb25seSBzb3VyY2VzOiByZWFkb25seSBUaW1lVHJhdmVsU291cmNlW107XG4gIHByaXZhdGUgcmVhZG9ubHkgb3B0aW9uczogVGltZVRyYXZlbE9wdGlvbnM8VE1ldGE+O1xuICBwcml2YXRlIHJlYWRvbmx5IF9tYXJrczogTWFya1tdO1xuICBwcml2YXRlIHN0ZXA6IG51bWJlcjtcbiAgLyoqIFRoZSBsYXN0IGZvbGQncyB3b3JraW5nIGNvcHksIHNvIGEgc3RlcCBmb3J3YXJkIGFwcGxpZXMgb25lIGJ1bmRsZSAoOS4yNS4wKS4gKi9cbiAgcHJpdmF0ZSBmb2xkTWVtbzogRm9sZE1lbW8gfCB1bmRlZmluZWQ7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgc291cmNlczogcmVhZG9ubHkgVGltZVRyYXZlbFNvdXJjZVtdLFxuICAgIG9wdGlvbnM6IFRpbWVUcmF2ZWxPcHRpb25zPFRNZXRhPixcbiAgICBwYXRoPzogc3RyaW5nLFxuICAgIHBhcmVudD86IFRpbWVUcmF2ZWw8VE1ldGE+LFxuICAgIG1vdW50UnVudGltZVN0YWdlSWQ/OiBzdHJpbmcsXG4gICkge1xuICAgIHRoaXMuc291cmNlcyA9IHNvdXJjZXM7XG4gICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucztcbiAgICB0aGlzLnBhdGggPSBwYXRoO1xuICAgIHRoaXMucGFyZW50ID0gcGFyZW50O1xuICAgIHRoaXMubW91bnRSdW50aW1lU3RhZ2VJZCA9IG1vdW50UnVudGltZVN0YWdlSWQ7XG4gICAgdGhpcy5sZWdzID0gc291cmNlcy5tYXAoKHNvdXJjZSkgPT4gcmVhZFNvdXJjZShzb3VyY2UpKTtcbiAgICB0aGlzLnNvdXJjZUNvdW50ID0gc291cmNlcy5sZW5ndGg7XG5cbiAgICAvLyBUaGUgc2hpcHBlZCBzdHJhdGVneSBoYXMgbm8gdm9jYWJ1bGFyeSBvZiBpdHMgb3duIChgbWV0YWAgaXMgbmV2ZXIgc2V0KSxcbiAgICAvLyBzbyBpdCBzZXJ2ZXMgYW55IGBUTWV0YWAgYSBjYWxsZXIgYXNrZWQgZm9yLlxuICAgIGNvbnN0IHN0cmF0ZWd5ID0gb3B0aW9ucy5zdHJhdGVneSA/PyAoY29tbWl0U3RvcHNTdHJhdGVneSBhcyBUaW1lVHJhdmVsU3RyYXRlZ3k8VE1ldGE+KTtcbiAgICAvLyBPTkUgQ0FMTCBQRVIgU09VUkNFLCB3aXRoIHRoYXQgc291cmNlJ3Mgb3duIGxvZyBhbmQgdHJlZTogYSBzdHJhdGVneVxuICAgIC8vIG5ldmVyIGhhcyB0byBrbm93IGl0IGlzIHBhcnQgb2YgYSBjaGFpbiwgYW5kIGl0cyBpbmRpY2VzIHN0YXkgbG9jYWwgdG9cbiAgICAvLyB0aGUgbGVnIGl0IHdhcyBoYW5kZWQuXG4gICAgY29uc3QgcGVyU291cmNlID0gdGhpcy5sZWdzLm1hcCgobGVnLCBpKSA9PlxuICAgICAgc3RyYXRlZ3kuc3RvcHNGb3IobGVnLmxvZywgcmVhZFRyZWUoc291cmNlc1tpXS5leGVjdXRpb25UcmVlKSwgc291cmNlc1tpXS5zdWJmbG93UmVzdWx0cyksXG4gICAgKTtcbiAgICB0aGlzLnN0b3BzID0gT2JqZWN0LmZyZWV6ZShzb3VyY2VzLmxlbmd0aCA9PT0gMSA/IHBlclNvdXJjZVswXSA6IGNoYWluU3RvcHMocGVyU291cmNlKSk7XG4gICAgdGhpcy5fbWFya3MgPSBbLi4uKG9wdGlvbnMubWFya3MgPz8gW10pXTtcbiAgICB0aGlzLnN0ZXAgPSAwO1xuICB9XG5cbiAgLy8g4pSA4pSAIFBvc2l0aW9uIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIGF0KCk6IFN0b3A8VE1ldGE+IHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5zdG9wc1t0aGlzLnN0ZXBdO1xuICB9XG5cbiAgcHJpdmF0ZSBtb3ZlVG8oc3RlcDogbnVtYmVyKTogTW92ZTxUTWV0YT4ge1xuICAgIGNvbnN0IGZyb20gPSB0aGlzLmF0KCk7XG4gICAgdGhpcy5zdGVwID0gc3RlcDtcbiAgICByZXR1cm4geyBtb3ZlZDogdHJ1ZSwgZnJvbSwgdG86IHRoaXMuc3RvcHNbc3RlcF0gfTtcbiAgfVxuXG4gIC8qKiBMYXcgMjogYSByZWZ1c2FsIG5ldmVyIHRvdWNoZXMgYHRoaXMuc3RlcGAuICovXG4gIHByaXZhdGUgcmVmdXNlKHJlYXNvbjogJ2NsYW1wZWQnIHwgJ21pc3MnIHwgJ2VtcHR5JywgbmVhcmVzdD86IFN0b3A8VE1ldGE+KTogTW92ZTxUTWV0YT4ge1xuICAgIGNvbnN0IGF0ID0gdGhpcy5hdCgpO1xuICAgIHJldHVybiBuZWFyZXN0ID8geyBtb3ZlZDogZmFsc2UsIHJlYXNvbiwgYXQsIG5lYXJlc3QgfSA6IHsgbW92ZWQ6IGZhbHNlLCByZWFzb24sIGF0IH07XG4gIH1cblxuICBmaXJzdCgpOiBNb3ZlPFRNZXRhPiB7XG4gICAgaWYgKHRoaXMuc3RvcHMubGVuZ3RoID09PSAwKSByZXR1cm4gdGhpcy5yZWZ1c2UoJ2VtcHR5Jyk7XG4gICAgaWYgKHRoaXMuc3RlcCA9PT0gMCkgcmV0dXJuIHRoaXMucmVmdXNlKCdjbGFtcGVkJyk7XG4gICAgcmV0dXJuIHRoaXMubW92ZVRvKDApO1xuICB9XG5cbiAgbGFzdCgpOiBNb3ZlPFRNZXRhPiB7XG4gICAgaWYgKHRoaXMuc3RvcHMubGVuZ3RoID09PSAwKSByZXR1cm4gdGhpcy5yZWZ1c2UoJ2VtcHR5Jyk7XG4gICAgY29uc3QgZW5kID0gdGhpcy5zdG9wcy5sZW5ndGggLSAxO1xuICAgIGlmICh0aGlzLnN0ZXAgPT09IGVuZCkgcmV0dXJuIHRoaXMucmVmdXNlKCdjbGFtcGVkJyk7XG4gICAgcmV0dXJuIHRoaXMubW92ZVRvKGVuZCk7XG4gIH1cblxuICBwcmV2KCk6IE1vdmU8VE1ldGE+IHtcbiAgICBpZiAodGhpcy5zdG9wcy5sZW5ndGggPT09IDApIHJldHVybiB0aGlzLnJlZnVzZSgnZW1wdHknKTtcbiAgICBpZiAodGhpcy5zdGVwID09PSAwKSByZXR1cm4gdGhpcy5yZWZ1c2UoJ2NsYW1wZWQnKTtcbiAgICByZXR1cm4gdGhpcy5tb3ZlVG8odGhpcy5zdGVwIC0gMSk7XG4gIH1cblxuICBuZXh0KCk6IE1vdmU8VE1ldGE+IHtcbiAgICBpZiAodGhpcy5zdG9wcy5sZW5ndGggPT09IDApIHJldHVybiB0aGlzLnJlZnVzZSgnZW1wdHknKTtcbiAgICBpZiAodGhpcy5zdGVwID49IHRoaXMuc3RvcHMubGVuZ3RoIC0gMSkgcmV0dXJuIHRoaXMucmVmdXNlKCdjbGFtcGVkJyk7XG4gICAgcmV0dXJuIHRoaXMubW92ZVRvKHRoaXMuc3RlcCArIDEpO1xuICB9XG5cbiAganVtcFRvKHRhcmdldDogbnVtYmVyIHwgc3RyaW5nKTogTW92ZTxUTWV0YT4ge1xuICAgIGlmICh0aGlzLnN0b3BzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIHRoaXMucmVmdXNlKCdlbXB0eScpO1xuXG4gICAgaWYgKHR5cGVvZiB0YXJnZXQgPT09ICdudW1iZXInKSB7XG4gICAgICBjb25zdCBzdGVwID0gTWF0aC50cnVuYyh0YXJnZXQpO1xuICAgICAgaWYgKE51bWJlci5pc05hTihzdGVwKSkgcmV0dXJuIHRoaXMucmVmdXNlKCdtaXNzJyk7XG4gICAgICBpZiAoc3RlcCA8IDApIHJldHVybiB0aGlzLnJlZnVzZSgnY2xhbXBlZCcsIHRoaXMuc3RvcHNbMF0pO1xuICAgICAgaWYgKHN0ZXAgPiB0aGlzLnN0b3BzLmxlbmd0aCAtIDEpIHJldHVybiB0aGlzLnJlZnVzZSgnY2xhbXBlZCcsIHRoaXMuc3RvcHNbdGhpcy5zdG9wcy5sZW5ndGggLSAxXSk7XG4gICAgICBpZiAoc3RlcCA9PT0gdGhpcy5zdGVwKSByZXR1cm4gdGhpcy5yZWZ1c2UoJ2NsYW1wZWQnKTtcbiAgICAgIHJldHVybiB0aGlzLm1vdmVUbyhzdGVwKTtcbiAgICB9XG5cbiAgICAvLyBgJydgIGlzIG5vdCBhbiBhZGRyZXNzOiBpdCBpcyB3aGF0IHRoZSBib29rZW5kcyBhbmQgYW55IHByZS1zdGFnZVxuICAgIC8vIHJvb3QgY29tbWl0IGNhcnJ5LiBUaG9zZSBhcmUgcmVhY2hlZCBieSBzdGVwLCBuZXZlciBieSBpZC5cbiAgICBpZiAodGFyZ2V0ID09PSAnJykgcmV0dXJuIHRoaXMucmVmdXNlKCdtaXNzJyk7XG4gICAgY29uc3QgaGl0ID0gdGhpcy5zdG9wcy5maW5kKChzdG9wKSA9PiBzdG9wLnJ1bnRpbWVTdGFnZUlkID09PSB0YXJnZXQpO1xuICAgIGlmICghaGl0KSByZXR1cm4gdGhpcy5yZWZ1c2UoJ21pc3MnLCB0aGlzLm5lYXJlc3RUbyh0YXJnZXQpKTtcbiAgICBpZiAoaGl0LnN0ZXAgPT09IHRoaXMuc3RlcCkgcmV0dXJuIHRoaXMucmVmdXNlKCdjbGFtcGVkJyk7XG4gICAgcmV0dXJuIHRoaXMubW92ZVRvKGhpdC5zdGVwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgY2xvc2VzdCBuYW1hYmxlIHN0b3AgZm9yIGEgYHJ1bnRpbWVTdGFnZUlkYCB0aGF0IGlzIG5vdCBvbiB0aGlzIGF4aXM6XG4gICAqIHRoZSBsYXN0IHN0b3Agb2YgdGhlIHNhbWUgU1RBR0UgKGEgZGlmZmVyZW50IGl0ZXJhdGlvbiBvZiB0aGUgc2FtZSBub2RlKSxcbiAgICogZWxzZSB0aGUgbGFzdCBzdG9wIHdob3NlIGNvbW1pdCBwcmVjZWRlcyB0aGUgbWlzc2VkIGlkJ3MgZXhlY3V0aW9uIGluZGV4LlxuICAgKiBOYW1pbmcgYSBuZWlnaGJvdXIgaXMgYSBjb3VydGVzeSBmb3IgdGhlIFVJIOKAlCBpdCBuZXZlciBtb3ZlcyB0aGUgY3Vyc29yLlxuICAgKi9cbiAgcHJpdmF0ZSBuZWFyZXN0VG8ocnVudGltZVN0YWdlSWQ6IHN0cmluZyk6IFN0b3A8VE1ldGE+IHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoIWlzRXhlY3V0aW9uS2V5KHJ1bnRpbWVTdGFnZUlkKSkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBjb25zdCBzdGFnZVBhcnQgPSBzdGFnZUlkT2YocnVudGltZVN0YWdlSWQpO1xuICAgIGNvbnN0IHdhbnRlZCA9IGV4ZWN1dGlvbkluZGV4T2YocnVudGltZVN0YWdlSWQpO1xuXG4gICAgbGV0IHNhbWVTdGFnZTogU3RvcDxUTWV0YT4gfCB1bmRlZmluZWQ7XG4gICAgbGV0IGJ5SW5kZXg6IFN0b3A8VE1ldGE+IHwgdW5kZWZpbmVkO1xuICAgIGZvciAoY29uc3Qgc3RvcCBvZiB0aGlzLnN0b3BzKSB7XG4gICAgICBpZiAoIWlzRXhlY3V0aW9uS2V5KHN0b3AucnVudGltZVN0YWdlSWQpKSBjb250aW51ZTtcbiAgICAgIGlmIChzdGFnZUlkT2Yoc3RvcC5ydW50aW1lU3RhZ2VJZCkgPT09IHN0YWdlUGFydCkgc2FtZVN0YWdlID0gc3RvcDtcbiAgICAgIGlmICghTnVtYmVyLmlzTmFOKHdhbnRlZCkpIHtcbiAgICAgICAgY29uc3QgaWR4ID0gZXhlY3V0aW9uSW5kZXhPZihzdG9wLnJ1bnRpbWVTdGFnZUlkKTtcbiAgICAgICAgaWYgKCFOdW1iZXIuaXNOYU4oaWR4KSAmJiBpZHggPD0gd2FudGVkKSBieUluZGV4ID0gc3RvcDtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHNhbWVTdGFnZSA/PyBieUluZGV4O1xuICB9XG5cbiAgLy8g4pSA4pSAIFJlYWRpbmcg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgc3RhdGVBdChzdG9wPzogU3RvcDxUTWV0YT4pOiBGb2xkZWRTdGF0ZSB7XG4gICAgY29uc3QgdGFyZ2V0ID0gc3RvcCA/PyB0aGlzLmF0KCk7XG4gICAgY29uc3QgbGVnID0gdGFyZ2V0Py5zb3VyY2VJZHggPz8gMDtcbiAgICBjb25zdCBmb2xkID0gZm9sZExlZ3NGcm9tKHRoaXMubGVncywgbGVnLCB0YXJnZXQgPyB0YXJnZXQubGFzdENvbW1pdElkeCA6IC0xLCB0aGlzLmZvbGRNZW1vKTtcbiAgICB0aGlzLmZvbGRNZW1vID0gZm9sZC5tZW1vO1xuICAgIGNvbnN0IGZvbGRlZCA9IGZvbGQuZm9sZGVkO1xuICAgIC8vIFdoaWNoIGxlZyB0aGUgaW5kZXggYmVsb25ncyB0bywgYnV0IG9ubHkgd2hlbiB0aGVyZSBpcyBtb3JlIHRoYW4gb25lIOKAlFxuICAgIC8vIGEgc2luZ2xlLXNvdXJjZSBmb2xkIGtlZXBzIHRoZSA5LjE3LjAgc2hhcGUgZXhhY3RseS5cbiAgICByZXR1cm4gdGhpcy5sZWdzLmxlbmd0aCA+IDEgPyB7IC4uLmZvbGRlZCwgc291cmNlSWR4OiBsZWcgfSA6IGZvbGRlZDtcbiAgfVxuXG4gIGNoYW5nZWRTaW5jZShmcm9tPzogU3RvcDxUTWV0YT4pOiByZWFkb25seSBzdHJpbmdbXSB7XG4gICAgY29uc3QgdG8gPSB0aGlzLmF0KCk7XG4gICAgaWYgKCF0bykgcmV0dXJuIE9iamVjdC5mcmVlemUoW10pO1xuICAgIGNvbnN0IHN0YXJ0ID0gZnJvbSA/PyB0aGlzLnN0b3BzW3RoaXMuc3RlcCAtIDFdO1xuICAgIC8vIE5vIGVhcmxpZXIgc3RvcCAod2UgYXJlIGF0IGAnc3RhcnQnYCkg4oeSIGV2ZXJ5dGhpbmcgdXAgdG8gaGVyZTogbm90aGluZ1xuICAgIC8vIG9uIGEgcnVuIGN1cnNvciwgYW5kIHRoZSBzdWJmbG93J3MgYGlucHV0TWFwcGVyYCBzZWVkIG9uIGEgZHJpbGxlZCBvbmVcbiAgICAvLyAodGhlIHN0YXJ0IGJvb2tlbmQgY292ZXJzIHRoZSBzZWVkIHRoYXQgcHJlY2VkZXMgc3RhZ2Ugb25lIOKAlCBgY29tbWl0U3RvcHNgKS5cbiAgICBjb25zdCB0b0xlZyA9IHRvLnNvdXJjZUlkeCA/PyAwO1xuICAgIGNvbnN0IGZyb21MZWcgPSBzdGFydCA/IHN0YXJ0LnNvdXJjZUlkeCA/PyAwIDogdG9MZWc7XG4gICAgY29uc3QgYWZ0ZXJJZHggPSBzdGFydCA/IHN0YXJ0Lmxhc3RDb21taXRJZHggOiAtMTtcbiAgICBjb25zdCBrZXlzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgLy8gQSByYW5nZSB0aGF0IGNyb3NzZXMgYSBjaGFpbiBzZWFtIGlzIHdhbGtlZCBsZWcgYnkgbGVnOiB0aGUgdGFpbCBvZiB0aGVcbiAgICAvLyBsZWcgaXQgc3RhcnRlZCBpbiwgZXZlcnkgbGVnIGluIGJldHdlZW4gd2hvbGUsIHRoZW4gdGhlIGhlYWQgb2YgdGhlIGxlZ1xuICAgIC8vIGl0IGVuZHMgaW4uIEJhY2t3YXJkcyByYW5nZXMgd2FsayBub3RoaW5nIGFuZCBnaXZlIGBbXWAsIGFzIGJlZm9yZS5cbiAgICBmb3IgKGxldCBsZWcgPSBmcm9tTGVnOyBsZWcgPD0gdG9MZWcgJiYgbGVnIDwgdGhpcy5sZWdzLmxlbmd0aDsgbGVnKyspIHtcbiAgICAgIGNvbnN0IGxvZyA9IHRoaXMubGVnc1tsZWddLmxvZztcbiAgICAgIGNvbnN0IGxvID0gbGVnID09PSBmcm9tTGVnID8gYWZ0ZXJJZHggKyAxIDogMDtcbiAgICAgIGNvbnN0IGhpID0gbGVnID09PSB0b0xlZyA/IHRvLmxhc3RDb21taXRJZHggOiBsb2cubGVuZ3RoIC0gMTtcbiAgICAgIGZvciAobGV0IGkgPSBsbzsgaSA8PSBoaTsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGJ1bmRsZSA9IGxvZ1tpXTtcbiAgICAgICAgaWYgKCFidW5kbGUpIGNvbnRpbnVlO1xuICAgICAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIGJ1bmRsZS50cmFjZSkga2V5cy5hZGQoZW50cnkucGF0aCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBPYmplY3QuZnJlZXplKFsuLi5rZXlzXS5zb3J0KCkpO1xuICB9XG5cbiAgLy8g4pSA4pSAIE1hcmtzIChsYXcgNDogYmVzaWRlIHRoZSBsb2csIG5ldmVyIGluIGl0KSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBtYXJrKG5hbWU6IHN0cmluZywgc3RvcD86IFN0b3A8VE1ldGE+KTogTWFyayB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgdGFyZ2V0ID0gc3RvcCA/PyB0aGlzLmF0KCk7XG4gICAgaWYgKCF0YXJnZXQpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgY29uc3QgZW50cnk6IE1hcmsgPSBPYmplY3QuZnJlZXplKHsgbmFtZSwgcnVudGltZVN0YWdlSWQ6IHRhcmdldC5ydW50aW1lU3RhZ2VJZCwgc3RlcDogdGFyZ2V0LnN0ZXAgfSk7XG4gICAgY29uc3QgZXhpc3RpbmcgPSB0aGlzLl9tYXJrcy5maW5kSW5kZXgoKG0pID0+IG0ubmFtZSA9PT0gbmFtZSk7XG4gICAgaWYgKGV4aXN0aW5nID49IDApIHRoaXMuX21hcmtzW2V4aXN0aW5nXSA9IGVudHJ5O1xuICAgIGVsc2UgdGhpcy5fbWFya3MucHVzaChlbnRyeSk7XG4gICAgcmV0dXJuIGVudHJ5O1xuICB9XG5cbiAgbWFya3MoKTogcmVhZG9ubHkgTWFya1tdIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShbLi4udGhpcy5fbWFya3NdKTtcbiAgfVxuXG4gIGp1bXBUb01hcmsobmFtZTogc3RyaW5nKTogTW92ZTxUTWV0YT4ge1xuICAgIGlmICh0aGlzLnN0b3BzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIHRoaXMucmVmdXNlKCdlbXB0eScpO1xuICAgIGNvbnN0IGVudHJ5ID0gdGhpcy5fbWFya3MuZmluZCgobSkgPT4gbS5uYW1lID09PSBuYW1lKTtcbiAgICBpZiAoIWVudHJ5KSByZXR1cm4gdGhpcy5yZWZ1c2UoJ21pc3MnKTtcbiAgICAvLyBSZXNvbHZlIGJ5IHJ1bnRpbWVTdGFnZUlkIGZpcnN0IOKAlCB0aGUgYWRkcmVzcyB0aGF0IHN1cnZpdmVzIGEgY2hhbmdlIG9mXG4gICAgLy8gc3RyYXRlZ3kg4oCUIGFuZCBmYWxsIGJhY2sgdG8gdGhlIHJlbWVtYmVyZWQgc3RlcCBvbmx5IGZvciB0aGUgYm9va2VuZHMsXG4gICAgLy8gd2hpY2ggaGF2ZSBubyBzdGFnZSBpZCBvZiB0aGVpciBvd24uXG4gICAgY29uc3QgYnlJZCA9IGVudHJ5LnJ1bnRpbWVTdGFnZUlkXG4gICAgICA/IHRoaXMuc3RvcHMuZmluZCgoc3RvcCkgPT4gc3RvcC5ydW50aW1lU3RhZ2VJZCA9PT0gZW50cnkucnVudGltZVN0YWdlSWQpXG4gICAgICA6IHRoaXMuc3RvcHNbZW50cnkuc3RlcF07XG4gICAgaWYgKCFieUlkKSByZXR1cm4gdGhpcy5yZWZ1c2UoJ21pc3MnLCB0aGlzLm5lYXJlc3RUbyhlbnRyeS5ydW50aW1lU3RhZ2VJZCkpO1xuICAgIGlmIChieUlkLnN0ZXAgPT09IHRoaXMuc3RlcCkgcmV0dXJuIHRoaXMucmVmdXNlKCdjbGFtcGVkJyk7XG4gICAgcmV0dXJuIHRoaXMubW92ZVRvKGJ5SWQuc3RlcCk7XG4gIH1cblxuICAvLyDilIDilIAgRHJpbGxpbmcgKGxhdyAxOiBhIHNlcGFyYXRlIGN1cnNvciwgbm90IGEgc2Vjb25kIHBvc2l0aW9uKSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBkcmlsbChtb3VudFJ1bnRpbWVTdGFnZUlkOiBzdHJpbmcpOiBUaW1lVHJhdmVsPFRNZXRhPiB8IHVuZGVmaW5lZCB7XG4gICAgLy8gT24gYSBjaGFpbiwgdGhlIG1vdW50IGlzIGxvb2tlZCBmb3IgaW4gZXZlcnkgbGVnIOKAlCBhIHN1YmZsb3cgdGhhdCByYW5cbiAgICAvLyBiZWZvcmUgdGhlIHBhdXNlIGlzIGluIHRoZSBmaXJzdCBzbmFwc2hvdCdzIHJlc3VsdHMsIG9uZSB0aGF0IHJhbiBhZnRlclxuICAgIC8vIGlzIGluIHRoZSBzZWNvbmQncy4gSWRzIGFyZSB1bmlxdWUgYWNyb3NzIGEgc291bmQgY2hhaW4gKGNoYWluLnRzXG4gICAgLy8gcmVmdXNlcyBvbmUgd2hlcmUgdGhleSBhcmUgbm90KSwgc28gdGhlIGZpcnN0IGhpdCBpcyB0aGUgb25seSBoaXQuXG4gICAgbGV0IHJlc3VsdHM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgdW5kZWZpbmVkO1xuICAgIGxldCByZXN1bHQ6IFN1YmZsb3dSZXN1bHRTaGFwZSB8IHVuZGVmaW5lZDtcbiAgICBmb3IgKGNvbnN0IHNvdXJjZSBvZiB0aGlzLnNvdXJjZXMpIHtcbiAgICAgIC8vIEEgc3RvcmVkIHJlY29yZGluZydzIHJlc3VsdHMgYXJlIHBhcnNlZCBKU09OOiByZWFkIHRoZW0gYXMgYSBtYXAgb25seVxuICAgICAgLy8gd2hlbiB0aGV5IGFyZSBvbmUsIGFuZCBhcyBcIm5vIHN1YmZsb3dzXCIgb3RoZXJ3aXNlLlxuICAgICAgaWYgKCFpc1BsYWluaXNoKHNvdXJjZS5zdWJmbG93UmVzdWx0cykpIGNvbnRpbnVlO1xuICAgICAgY29uc3QgaGl0ID0gc291cmNlLnN1YmZsb3dSZXN1bHRzW21vdW50UnVudGltZVN0YWdlSWRdIGFzIFN1YmZsb3dSZXN1bHRTaGFwZSB8IHVuZGVmaW5lZDtcbiAgICAgIGlmIChoaXQpIHtcbiAgICAgICAgcmVzdWx0cyA9IHNvdXJjZS5zdWJmbG93UmVzdWx0cztcbiAgICAgICAgcmVzdWx0ID0gaGl0O1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgdHJlZSA9IHJlc3VsdD8udHJlZUNvbnRleHQ7XG4gICAgaWYgKCFyZXN1bHRzIHx8ICFyZXN1bHQgfHwgIXRyZWUgfHwgIUFycmF5LmlzQXJyYXkodHJlZS5oaXN0b3J5KSkgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgIC8vIGBwYXRoYCBpcyB0aGUgc3ViZmxvdyBQQVRIIOKAlCB0aGUgc2FtZSBzdHJpbmcgZm9yIGV2ZXJ5IGl0ZXJhdGlvbiBvZiBhXG4gICAgLy8gbW91bnQgaW5zaWRlIGEgbG9vcC4gYG1vdW50UnVudGltZVN0YWdlSWRgIGlzIHRoZSBpdGVyYXRpb24gYWN0dWFsbHlcbiAgICAvLyBvcGVuZWQsIHNvIGEgVUkgY2FuIGxhYmVsIGFuZCBrZXkgdGhyZWUgZHJpbGwgcGFuZWxzIG92ZXIgYHNmeCMyYCxcbiAgICAvLyBgc2Z4IzhgLCBgc2Z4IzE0YCBhcGFydCBpbnN0ZWFkIG9mIGNhbGxpbmcgYWxsIHRocmVlICdzZngnLlxuICAgIGNvbnN0IGNoaWxkUGF0aCA9IHJlc3VsdC5zdWJmbG93SWQgPz8gbW91bnRSdW50aW1lU3RhZ2VJZDtcbiAgICBjb25zdCBjaGlsZDogVGltZVRyYXZlbFNvdXJjZSA9IHtcbiAgICAgIC8vIFJvd3MgYXJlIG5hcnJvd2VkIHBlciBidW5kbGUgd2hlbiB0aGUgY2hpbGQgcmVhZHMgdGhlbSDigJQgYSBzdG9yZWRcbiAgICAgIC8vIHJlY29yZGluZydzIGlubmVyIGhpc3RvcnkgbmVlZHMgbm8gY2FzdCBlaXRoZXIuXG4gICAgICBjb21taXRMb2c6IHRyZWUuaGlzdG9yeSxcbiAgICAgIGluaXRpYWxTdGF0ZTogdHJlZS5pbml0aWFsU3RhdGUsXG4gICAgICBleGVjdXRpb25UcmVlOiB0cmVlLnN0YWdlQ29udGV4dHMsXG4gICAgICAvLyBOZXN0ZWQgc3ViZmxvdyByZXN1bHRzIGFyZSBtZXJnZWQgVVAgaW50byBvbmUgZmxhdCwgZHVhbC1rZXllZCBtYXAsIHNvXG4gICAgICAvLyB0aGUgY2hpbGQgY2FuIGRyaWxsIGZ1cnRoZXIgdGhyb3VnaCB0aGUgc2FtZSBtYXAuXG4gICAgICBzdWJmbG93UmVzdWx0czogcmVzdWx0cyxcbiAgICB9O1xuICAgIHJldHVybiBuZXcgQ3Vyc29yPFRNZXRhPihbY2hpbGRdLCB7IHN0cmF0ZWd5OiB0aGlzLm9wdGlvbnMuc3RyYXRlZ3kgfSwgY2hpbGRQYXRoLCB0aGlzLCBtb3VudFJ1bnRpbWVTdGFnZUlkKTtcbiAgfVxufVxuXG4vKipcbiAqIFJlLXN0ZXAgcGVyLXNvdXJjZSBzdG9wcyBpbnRvIE9ORSBheGlzLlxuICpcbiAqIFRoZSBJTlRFUklPUiBib29rZW5kcyBnbzogYSBgJ3N0YXJ0J2Agb24gYW55IGxlZyBidXQgdGhlIGZpcnN0LCBhbmQgYW5cbiAqIGAnZW5kJ2Agb24gYW55IGxlZyBidXQgdGhlIGxhc3QsIGFyZSBib29rZW5kcyBvZiBhIGxlZyBhbmQgbm90IG9mIHRoZSBydW4g4oCUXG4gKiBrZWVwaW5nIHRoZW0gd291bGQgcHV0IFwidGhlIHJ1biBpcyBvdmVyXCIgaW4gdGhlIG1pZGRsZSBvZiB0aGUgYXhpcy4gVGhlXG4gKiBjb21taXRzIHRoZXkgY292ZXJlZCBhcmUgbm90IG9ycGhhbmVkOiBhIGZvbGQgYWx3YXlzIHJlcGxheXMgaXRzIGxlZyBmcm9tXG4gKiB0aGF0IGxlZydzIG93biBiYXNlLCBhbmQgYGNoYW5nZWRTaW5jZWAgd2Fsa3MgYSBzZWFtLWNyb3NzaW5nIHJhbmdlIGxlZyBieVxuICogbGVnIChpbmNsdWRpbmcgdGhlIGhlYWQgb2YgdGhlIGxlZyBpdCBlbmRzIGluKS4gVGhlIHN0b3BzJyBgY29tbWl0SWR4YCAvXG4gKiBgbGFzdENvbW1pdElkeGAgcmFuZ2VzIFBBUlRJVElPTiBFQUNIIExFRywgbmV2ZXIgc3BhbiB0aGUgc2VhbTogYSBzdG9wJ3NcbiAqIHJhbmdlIGVuZHMgYXQgaXRzIG93biBsZWcncyBsYXN0IGluZGV4LCBhbmQgdGhlIG5leHQgbGVnJ3MgZmlyc3Qgc3RvcCBvcGVuc1xuICogYXQgdGhhdCBsZWcncyAwLlxuICovXG5mdW5jdGlvbiBjaGFpblN0b3BzPFRNZXRhPihwZXJTb3VyY2U6IHJlYWRvbmx5IFN0b3A8VE1ldGE+W11bXSk6IFN0b3A8VE1ldGE+W10ge1xuICAvLyBcIkludGVyaW9yXCIgaXMgbWVhc3VyZWQgYWdhaW5zdCB0aGUgbGVncyB0aGF0IGFjdHVhbGx5IENPTlRSSUJVVEUgc3RvcHM6IGFcbiAgLy8gbGVnIHdob3NlIGxvZyB3YXMgZW1wdHkgaGFzIG5vIGJvb2tlbmRzIHRvIGRyb3AgYW5kIG11c3Qgbm90IG1ha2UgaXRzXG4gIC8vIG5laWdoYm91cidzIGAnc3RhcnQnYCBvciBgJ2VuZCdgIGludGVyaW9yIOKAlCB0aGUgY2hhaW5lZCBheGlzIHN0aWxsIG9wZW5zXG4gIC8vIHdpdGggdGhlIGZpcnN0IHN0b3AgdGhhdCBleGlzdHMgYW5kIGNsb3NlcyB3aXRoIHRoZSBsYXN0LlxuICBjb25zdCBjb250cmlidXRpbmcgPSBwZXJTb3VyY2UubWFwKChzdG9wcykgPT4gc3RvcHMubGVuZ3RoID4gMCk7XG4gIGNvbnN0IGZpcnN0TGVnID0gY29udHJpYnV0aW5nLmluZGV4T2YodHJ1ZSk7XG4gIGNvbnN0IGxhc3RMZWcgPSBjb250cmlidXRpbmcubGFzdEluZGV4T2YodHJ1ZSk7XG4gIGNvbnN0IG91dDogU3RvcDxUTWV0YT5bXSA9IFtdO1xuICBmb3IgKGNvbnN0IFtzb3VyY2VJZHgsIHN0b3BzXSBvZiBwZXJTb3VyY2UuZW50cmllcygpKSB7XG4gICAgZm9yIChjb25zdCBzdG9wIG9mIHN0b3BzKSB7XG4gICAgICBpZiAoc291cmNlSWR4ID4gZmlyc3RMZWcgJiYgc3RvcC5raW5kID09PSAnc3RhcnQnKSBjb250aW51ZTtcbiAgICAgIGlmIChzb3VyY2VJZHggPCBsYXN0TGVnICYmIHN0b3Aua2luZCA9PT0gJ2VuZCcpIGNvbnRpbnVlO1xuICAgICAgb3V0LnB1c2goeyAuLi5zdG9wLCBzdGVwOiBvdXQubGVuZ3RoLCBzb3VyY2VJZHggfSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBvdXQ7XG59XG5cbi8qKlxuICogT3BlbiBhIHJlYWRlcidzIGN1cnNvciBvdmVyIGEgZmluaXNoZWQgcnVuLlxuICpcbiAqIE5vdGhpbmcgaGVyZSBleGVjdXRlcyBhbnl0aGluZzogYHNuYXBzaG90YCBpcyBhIHJlY29yZCBvZiBhIHJ1biB0aGF0IGFscmVhZHlcbiAqIGhhcHBlbmVkLCBhbmQgZXZlcnkgcXVlc3Rpb24gaXMgYW5zd2VyZWQgYnkgcmVhZGluZyBpdC4gQSBzdG9yZWQgSlNPTlxuICogc25hcHNob3Qgd29ya3MgZXhhY3RseSBsaWtlIGEgbGl2ZSBvbmUg4oCUIHNpbmNlIDkuMTguMCBpdHMgYGNvbW1pdExvZ2AgbWF5IGJlXG4gKiBhbiB1bnZhbGlkYXRlZCBgdW5rbm93bltdYCwgbmFycm93ZWQgcGVyIGJ1bmRsZSB3aGVyZSB0aGUgZm9sZCByZWFkcyBpdCwgc29cbiAqIGEgcmVwbGF5ZWQgcmVjb3JkaW5nIG5lZWRzIG5vIGNhc3QuXG4gKlxuICogQHBhcmFtIHNuYXBzaG90IGBleGVjdXRvci5nZXRTbmFwc2hvdCgpYCwgb3IgYW55IG9iamVjdCB3aXRoIHRoZSBzYW1lXG4gKiAgIHNoYXBlIOKAlCBpbmNsdWRpbmcgb25lIHJvdW5kLXRyaXBwZWQgdGhyb3VnaCBKU09OLCBvciBhIHN1YmZsb3cgc3VidHJlZVxuICogICAoYGdldFN1YnRyZWVTbmFwc2hvdCgpYCwgd2hvc2UgbG9nIGlzIHNwZWxsZWQgYGhpc3RvcnlgKS4gQW4gQVJSQVkgb2YgdGhlbVxuICogICBpcyBhIENIQUlOOiBhIHBhdXNlIGFuZCBpdHMgcmVzdW1lIHJlYWQgYXMgb25lIGF4aXMgKHNlZSBiZWxvdykuXG4gKiBAcGFyYW0gb3B0aW9ucyBgc3RyYXRlZ3lgIGNob29zZXMgaG93IHN0b3BzIGFyZSBkZXJpdmVkIChkZWZhdWx0OlxuICogICBgY29tbWl0U3RvcHNgLCBvbmUgc3RvcCBwZXIgZXhlY3V0ZWQgc3RhZ2UpOyBgbWFya3NgIHNlZWRzIHRoZSBjdXJzb3Igd2l0aFxuICogICBib29rbWFya3MsIGUuZy4gcmVzdG9yZWQgZnJvbSBhIHNhdmVkIHJlYWRpbmcgc2Vzc2lvbi5cbiAqXG4gKiBAdGhyb3dzIHdoZW4gYSBjaGFpbiBpcyBub3QgaW4gcnVuIG9yZGVyLCBvciBpdHMgbGVncyBhcmUgbm90IGZyb20gb25lXG4gKiAgIGxpbmVhZ2Ug4oCUIHRocmVlIGNoZWNrcywgZWFjaCB3aXRoIGl0cyBvd24gcmVhc29uIChzZWUgYGNoYWluLnRzYCk6XG4gKiAgIG5vIGBydW50aW1lU3RhZ2VJZGAgbWF5IGFwcGVhciBpbiB0d28gbGVnczsgZWFjaCBsZWcncyBmaXJzdCBleGVjdXRpb25cbiAqICAgaW5kZXggbXVzdCBiZSBwYXN0IHRoZSBwcmV2aW91cyBsZWcncyBsYXN0ICh0aGUgZW5naW5lIG5ldmVyIHJlc2V0cyB0aGVcbiAqICAgY291bnRlciBhY3Jvc3MgYSByZXN1bWUpOyBhbmQgZWFjaCBsZWcncyBgaW5pdGlhbFN0YXRlYCBtdXN0IGRlZXAtZXF1YWxcbiAqICAgdGhlIHN0YXRlIHRoZSBsZWdzIGJlZm9yZSBpdCBmb2xkIHRvIOKAlCBvbiBhIHJlc3VtZSB0aGF0IGJhc2UgSVMgdGhlIHN0YXRlXG4gKiAgIGF0IHRoZSBwYXVzZSwgc28gYSBmb3JlaWduIGxlZyB3aG9zZSBpbmRpY2VzIG1lcmVseSBoYXBwZW4gdG8gYmUgaGlnaGVyXG4gKiAgIGlzIHJlZnVzZWQgdG9vLiBUaGUgdGhpcmQgY2hlY2sgcnVucyBvbmx5IHdoZXJlIHRoZSByZWNvcmQgYWxsb3dzIGl0OiB0aGVcbiAqICAgbGF0ZXIgbGVnIG11c3QgY2FycnkgYW4gYGluaXRpYWxTdGF0ZWAgYW5kIHRoZSBlYXJsaWVyIGxlZ3MgbXVzdCBmb2xkIGZyb21cbiAqICAgYSByZWFsIGJhc2Ugd2l0aCBubyB1bnJlYWRhYmxlIHJvd3M7IG90aGVyd2lzZSAoYW4gb2xkZXIgcmVjb3JkaW5nIHdpdGhcbiAqICAgbm8gYmFzZSkgdGhlIGNoYWluIHJlc3RzIG9uIHRoZSB0d28gaW5kZXggY2hlY2tzIGFsb25lLCBhbmQgdGhlIGZvbGQnc1xuICogICBgYmFzaXNgIHNheXMgd2hhdCBpdCBzdG9vZCBvbi5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgdHQgPSB0aW1lVHJhdmVsKGV4ZWN1dG9yLmdldFNuYXBzaG90KCkpO1xuICogdHQuanVtcFRvKCdzY29yZS1yaXNrIzQnKTtcbiAqIGNvbnNvbGUubG9nKHR0LmNoYW5nZWRTaW5jZSgpKTsgICAgICAgIC8vIFsncmlza1Njb3JlJywgJ3RpZXInXVxuICogY29uc29sZS5sb2codHQuc3RhdGVBdCgpLnN0YXRlKTsgICAgICAgLy8gc3RhdGUgYXMgdGhhdCBzdGFnZSBsZWZ0IGl0XG4gKiB0dC5tYXJrKCd0aGUgYmFkIG9uZScpO1xuICogY29uc3QgaW5uZXIgPSB0dC5kcmlsbCgnc2YtcGF5bWVudCM3Jyk7IC8vIGEgc2VwYXJhdGUgY3Vyc29yLCBpdHMgb3duIGxvZ1xuICpcbiAqIC8vIEEgcGF1c2UgYW5kIGl0cyByZXN1bWUsIHJlYWQgYXMgT05FIGF4aXM6XG4gKiBjb25zdCBjaGFpbmVkID0gdGltZVRyYXZlbChbcGF1c2VkU25hcHNob3QsIHJlc3VtZWRTbmFwc2hvdF0pO1xuICogY2hhaW5lZC5sYXN0KCk7ICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBydW4ncyByZWFsIGVuZFxuICogY2hhaW5lZC5hdCgpIS5zb3VyY2VJZHg7ICAgICAgICAgICAgICAgIC8vIDEg4oCUIHdoaWNoIGxlZyB0aGUgaW5kaWNlcyBhcmUgaW5cbiAqIGNoYWluZWQuanVtcFRvKCdhcHByb3ZlIzMnKTsgICAgICAgICAgICAvLyBmaW5kcyBpdCBpbiBlaXRoZXIgbGVnXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRpbWVUcmF2ZWw8VE1ldGEgPSB1bmtub3duPihcbiAgc25hcHNob3Q6IFRpbWVUcmF2ZWxTb3VyY2UgfCByZWFkb25seSBUaW1lVHJhdmVsU291cmNlW10sXG4gIG9wdGlvbnM6IFRpbWVUcmF2ZWxPcHRpb25zPFRNZXRhPiA9IHt9LFxuKTogVGltZVRyYXZlbDxUTWV0YT4ge1xuICBjb25zdCBzb3VyY2VzID0gQXJyYXkuaXNBcnJheShzbmFwc2hvdCkgPyAoc25hcHNob3QgYXMgcmVhZG9ubHkgVGltZVRyYXZlbFNvdXJjZVtdKSA6IFtzbmFwc2hvdCBhcyBUaW1lVHJhdmVsU291cmNlXTtcbiAgLy8gQSBvbmUtZWxlbWVudCBhcnJheSBpcyBub3QgYSBjaGFpbjogaXQgaXMgdGhlIHBsYWluIGN1cnNvciwgYW5kIHNraXBzIHRoZVxuICAvLyBsaW5lYWdlIGNoZWNrcyBhIHNpbmdsZSBzb3VyY2UgY2Fubm90IGZhaWwuXG4gIGlmIChzb3VyY2VzLmxlbmd0aCAhPT0gMSkge1xuICAgIGNvbnN0IHJlZnVzYWwgPSByZWZ1c2VDaGFpbihzb3VyY2VzLm1hcCgoc291cmNlKSA9PiByZWFkU291cmNlKHNvdXJjZSkpKTtcbiAgICBpZiAocmVmdXNhbCkgdGhyb3cgbmV3IEVycm9yKHJlZnVzYWwpO1xuICB9XG4gIHJldHVybiBuZXcgQ3Vyc29yPFRNZXRhPihzb3VyY2VzLCBvcHRpb25zKTtcbn1cbiJdfQ==
|