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,184 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* axis.ts — the shape of an axis, and the one safe way to narrow it.
|
|
4
|
-
*
|
|
5
|
-
* WHY THIS FILE EXISTS. `commitStops` returns `Stop[]`, and every strategy
|
|
6
|
-
* that COMPOSES it (keep the stages my domain recognises, drop the rest) rests
|
|
7
|
-
* on a shape the type never stated: `[start, …stages, end]` for a non-empty
|
|
8
|
-
* log, empty for an empty one. Each composer therefore wrote its own runtime
|
|
9
|
-
* guard against its own reading of the contract, plus a mocked-substrate test
|
|
10
|
-
* to prove the guard fires. That is one invariant, discovered three times, and
|
|
11
|
-
* the library that owns the invariant should be the one that states it.
|
|
12
|
-
*
|
|
13
|
-
* {@link splitAxis} states it. {@link filterStops} then does the whole
|
|
14
|
-
* composition — check the shape, keep what the caller keeps, RE-PARTITION the
|
|
15
|
-
* log so the dropped stages' commits are still folded somewhere, and mark the
|
|
16
|
-
* `'start'` bookend as carrying a prologue — because getting the
|
|
17
|
-
* re-partitioning right by hand is the other thing every composer had to
|
|
18
|
-
* rediscover.
|
|
19
|
-
*/
|
|
20
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
exports.filterStops = exports.splitAxis = void 0;
|
|
22
|
-
/**
|
|
23
|
-
* Split a strategy's stops into `{ start, stages, end }`, or say why it cannot.
|
|
24
|
-
*
|
|
25
|
-
* THE INVARIANT, stated once: for a non-EMPTY log, `commitStops` returns at
|
|
26
|
-
* least the two bookends, `'start'` first and `'end'` last, with one stop per
|
|
27
|
-
* executed stage in execution order between them. For an EMPTY log it returns
|
|
28
|
-
* `[]` — no bookends around nothing, because a cursor with nowhere to stand
|
|
29
|
-
* should say `reason: 'empty'` rather than offer two positions that are the
|
|
30
|
-
* same position.
|
|
31
|
-
*
|
|
32
|
-
* The two refusals are different facts and must not be collapsed: `'empty'`
|
|
33
|
-
* means the run committed nothing, `'not-bookended'` means a strategy broke
|
|
34
|
-
* the contract. A composer that treats them alike reports a broken strategy as
|
|
35
|
-
* an empty run.
|
|
36
|
-
*
|
|
37
|
-
* @example
|
|
38
|
-
* ```typescript
|
|
39
|
-
* import { commitStops, splitAxis } from 'footprintjs/trace';
|
|
40
|
-
*
|
|
41
|
-
* const axis = splitAxis(commitStops(snapshot.commitLog, snapshot.executionTree));
|
|
42
|
-
* if (axis.ok) {
|
|
43
|
-
* axis.start.commitIdx; // -1 — the fold base
|
|
44
|
-
* axis.stages.map((s) => s.label);
|
|
45
|
-
* axis.end.lastCommitIdx; // the last bundle in the log
|
|
46
|
-
* } else {
|
|
47
|
-
* axis.reason; // 'empty' | 'not-bookended'
|
|
48
|
-
* }
|
|
49
|
-
* ```
|
|
50
|
-
*/
|
|
51
|
-
function splitAxis(stops) {
|
|
52
|
-
const kinds = Object.freeze(stops.map((stop) => stop.kind));
|
|
53
|
-
if (stops.length === 0)
|
|
54
|
-
return { ok: false, reason: 'empty', kinds };
|
|
55
|
-
const start = stops[0];
|
|
56
|
-
const end = stops[stops.length - 1];
|
|
57
|
-
if (start.kind !== 'start' || end.kind !== 'end' || stops.length < 2) {
|
|
58
|
-
return { ok: false, reason: 'not-bookended', kinds };
|
|
59
|
-
}
|
|
60
|
-
return { ok: true, start, stages: Object.freeze(stops.slice(1, -1)), end };
|
|
61
|
-
}
|
|
62
|
-
exports.splitAxis = splitAxis;
|
|
63
|
-
/**
|
|
64
|
-
* `stop` retyped to the OUTPUT vocabulary, with any meta it already carried
|
|
65
|
-
* left behind. The input axis may itself be a filtered one (a Beat axis being
|
|
66
|
-
* narrowed into a Tag axis), and a `true` decision keeps the STOP, not the
|
|
67
|
-
* other strategy's classification: a `Stop<Tag>` whose `meta` is a Beat would
|
|
68
|
-
* be a lie the type could not catch. Only the decision may supply a meta.
|
|
69
|
-
*/
|
|
70
|
-
function retyped(stop) {
|
|
71
|
-
if (stop.meta === undefined)
|
|
72
|
-
return stop;
|
|
73
|
-
const out = {};
|
|
74
|
-
const fields = stop;
|
|
75
|
-
for (const key of Object.keys(fields))
|
|
76
|
-
if (key !== 'meta')
|
|
77
|
-
out[key] = fields[key];
|
|
78
|
-
return out;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Build a FILTERING strategy's axis out of another strategy's stops.
|
|
82
|
-
*
|
|
83
|
-
* The rule, in one sentence: keep the stages `keep` recognises, and give the
|
|
84
|
-
* survivors the log back.
|
|
85
|
-
*
|
|
86
|
-
* **Meta is the decision's, never inherited.** The input may already be a
|
|
87
|
-
* filtered axis carrying another strategy's `meta`; a `true` (or a meta-less
|
|
88
|
-
* object) keeps the stop and DROPS that meta, so a `Stop<TMeta>` never carries
|
|
89
|
-
* a value of some other type under `TMeta`. The bookends carry none either.
|
|
90
|
-
*
|
|
91
|
-
* **The survivors re-partition the log.** A dropped stage's commits still
|
|
92
|
-
* happened, so they fold into the stop that PRECEDES them: every kept stop's
|
|
93
|
-
* `lastCommitIdx` runs to just before the next kept stop begins. Nothing is
|
|
94
|
-
* orphaned and `stateAt(stop)` stays "the state that existed when the next
|
|
95
|
-
* kept stage started".
|
|
96
|
-
*
|
|
97
|
-
* **What that costs `'start'`, said out loud.** The commits before the first
|
|
98
|
-
* survivor have nowhere else to go, so `'start'` absorbs them: its fold is the
|
|
99
|
-
* run's base PLUS that prologue — the state the first stop READ, not the raw
|
|
100
|
-
* base. The returned start therefore carries `prologue: true` whenever it
|
|
101
|
-
* actually absorbed a stage, and a renderer that means "before anything ran"
|
|
102
|
-
* checks `kind === 'start' && !prologue`. That flag is the whole reason this
|
|
103
|
-
* helper exists rather than a `.filter()` call.
|
|
104
|
-
*
|
|
105
|
-
* **A log with nothing kept** yields the two bookends and nothing between
|
|
106
|
-
* them: `'start'` folds the whole log, `'end'` folds the whole log, and
|
|
107
|
-
* `jumpTo` on any stage id refuses with `reason: 'miss'`. An axis with nowhere
|
|
108
|
-
* meaningful to stand — which is the truthful shape for a run this strategy
|
|
109
|
-
* recognises nothing in, and NOT the `[]` that says the log was empty.
|
|
110
|
-
*
|
|
111
|
-
* @throws when `stops` is non-empty but not bookended — see {@link splitAxis}.
|
|
112
|
-
* Only a strategy can cause that; a run cannot, so it is a contract error
|
|
113
|
-
* and not a condition to fold into the data.
|
|
114
|
-
*
|
|
115
|
-
* @example
|
|
116
|
-
* ```typescript
|
|
117
|
-
* import { commitStops, filterStops } from 'footprintjs/trace';
|
|
118
|
-
* import type { Stop, TimeTravelStrategy } from 'footprintjs/trace';
|
|
119
|
-
*
|
|
120
|
-
* type Milestone = { kind: 'llm-turn' | 'tool-call'; label: string };
|
|
121
|
-
* declare function milestoneFor(runtimeStageId: string): Milestone | null;
|
|
122
|
-
*
|
|
123
|
-
* const milestoneStops: TimeTravelStrategy<Milestone> = {
|
|
124
|
-
* stopsFor: (log, tree) =>
|
|
125
|
-
* filterStops<Milestone>(commitStops(log, tree), (stop) => {
|
|
126
|
-
* const m = milestoneFor(stop.runtimeStageId);
|
|
127
|
-
* return m ? { label: m.label, meta: m } : null;
|
|
128
|
-
* }),
|
|
129
|
-
* };
|
|
130
|
-
*
|
|
131
|
-
* const cursor = timeTravel(snapshot, { strategy: milestoneStops });
|
|
132
|
-
* cursor.at()?.meta?.kind; // 'llm-turn' — no re-derivation
|
|
133
|
-
* cursor.stops[0].prologue; // true when stages ran before the first turn
|
|
134
|
-
* ```
|
|
135
|
-
*/
|
|
136
|
-
function filterStops(stops, keep) {
|
|
137
|
-
const axis = splitAxis(stops);
|
|
138
|
-
if (!axis.ok) {
|
|
139
|
-
if (axis.reason === 'empty')
|
|
140
|
-
return [];
|
|
141
|
-
throw new Error('filterStops: expected a bookended axis — [start, …stages, end] — got kinds ' +
|
|
142
|
-
`[${axis.kinds.join(', ')}]. Only a strategy can produce that shape; a run cannot.`);
|
|
143
|
-
}
|
|
144
|
-
const kept = [];
|
|
145
|
-
for (const stop of axis.stages) {
|
|
146
|
-
const decision = keep(stop);
|
|
147
|
-
if (!decision)
|
|
148
|
-
continue;
|
|
149
|
-
if (decision === true)
|
|
150
|
-
kept.push({ stop });
|
|
151
|
-
else
|
|
152
|
-
kept.push({ stop, label: decision.label, meta: decision.meta });
|
|
153
|
-
}
|
|
154
|
-
// The log's last index, taken from the `'end'` bookend rather than a length:
|
|
155
|
-
// `end` is the one stop guaranteed to fold the whole log, and this function
|
|
156
|
-
// is never handed the log itself.
|
|
157
|
-
const lastIdx = axis.end.lastCommitIdx;
|
|
158
|
-
const first = kept[0];
|
|
159
|
-
const out = [
|
|
160
|
-
{
|
|
161
|
-
...retyped(axis.start),
|
|
162
|
-
step: 0,
|
|
163
|
-
lastCommitIdx: first ? first.stop.commitIdx - 1 : lastIdx,
|
|
164
|
-
// Only when a STAGE was actually absorbed. An axis that kept everything
|
|
165
|
-
// has the same start it always had, and says nothing it need not say.
|
|
166
|
-
...(first && first.stop.step > 1 ? { prologue: true } : {}),
|
|
167
|
-
...(!first && axis.stages.length > 0 ? { prologue: true } : {}),
|
|
168
|
-
},
|
|
169
|
-
];
|
|
170
|
-
for (const [i, row] of kept.entries()) {
|
|
171
|
-
const next = kept[i + 1];
|
|
172
|
-
out.push({
|
|
173
|
-
...retyped(row.stop),
|
|
174
|
-
step: out.length,
|
|
175
|
-
lastCommitIdx: next ? next.stop.commitIdx - 1 : lastIdx,
|
|
176
|
-
...(row.label !== undefined ? { label: row.label } : {}),
|
|
177
|
-
...(row.meta !== undefined ? { meta: row.meta } : {}),
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
out.push({ ...retyped(axis.end), step: out.length });
|
|
181
|
-
return out;
|
|
182
|
-
}
|
|
183
|
-
exports.filterStops = filterStops;
|
|
184
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXhpcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvdGltZS10cmF2ZWwvYXhpcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBaUJHOzs7QUFJSDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTRCRztBQUNILFNBQWdCLFNBQVMsQ0FBa0IsS0FBNkI7SUFDdEUsTUFBTSxLQUFLLEdBQXdCLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDakYsSUFBSSxLQUFLLENBQUMsTUFBTSxLQUFLLENBQUM7UUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxDQUFDO0lBQ3JFLE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN2QixNQUFNLEdBQUcsR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztJQUNwQyxJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssT0FBTyxJQUFJLEdBQUcsQ0FBQyxJQUFJLEtBQUssS0FBSyxJQUFJLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDckUsT0FBTyxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLGVBQWUsRUFBRSxLQUFLLEVBQUUsQ0FBQztJQUN2RCxDQUFDO0lBQ0QsT0FBTyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQztBQUM3RSxDQUFDO0FBVEQs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Q3pCLEdBQUcsQ0FBQyxJQUFJLENBQUM7WUFDUCxHQUFHLE9BQU8sQ0FBUSxHQUFHLENBQUMsSUFBSSxDQUFDO1lBQzNCLElBQUksRUFBRSxHQUFHLENBQUMsTUFBTTtZQUNoQixhQUFhLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU87WUFDdkQsR0FBRyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxHQUFHLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUN4RCxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUksS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1NBQ3RELENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxPQUFPLENBQVEsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLElBQUksRUFBRSxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztJQUM1RCxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUM7QUFuREQsa0NBbURDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBheGlzLnRzIOKAlCB0aGUgc2hhcGUgb2YgYW4gYXhpcywgYW5kIHRoZSBvbmUgc2FmZSB3YXkgdG8gbmFycm93IGl0LlxuICpcbiAqIFdIWSBUSElTIEZJTEUgRVhJU1RTLiBgY29tbWl0U3RvcHNgIHJldHVybnMgYFN0b3BbXWAsIGFuZCBldmVyeSBzdHJhdGVneVxuICogdGhhdCBDT01QT1NFUyBpdCAoa2VlcCB0aGUgc3RhZ2VzIG15IGRvbWFpbiByZWNvZ25pc2VzLCBkcm9wIHRoZSByZXN0KSByZXN0c1xuICogb24gYSBzaGFwZSB0aGUgdHlwZSBuZXZlciBzdGF0ZWQ6IGBbc3RhcnQsIOKApnN0YWdlcywgZW5kXWAgZm9yIGEgbm9uLWVtcHR5XG4gKiBsb2csIGVtcHR5IGZvciBhbiBlbXB0eSBvbmUuIEVhY2ggY29tcG9zZXIgdGhlcmVmb3JlIHdyb3RlIGl0cyBvd24gcnVudGltZVxuICogZ3VhcmQgYWdhaW5zdCBpdHMgb3duIHJlYWRpbmcgb2YgdGhlIGNvbnRyYWN0LCBwbHVzIGEgbW9ja2VkLXN1YnN0cmF0ZSB0ZXN0XG4gKiB0byBwcm92ZSB0aGUgZ3VhcmQgZmlyZXMuIFRoYXQgaXMgb25lIGludmFyaWFudCwgZGlzY292ZXJlZCB0aHJlZSB0aW1lcywgYW5kXG4gKiB0aGUgbGlicmFyeSB0aGF0IG93bnMgdGhlIGludmFyaWFudCBzaG91bGQgYmUgdGhlIG9uZSB0aGF0IHN0YXRlcyBpdC5cbiAqXG4gKiB7QGxpbmsgc3BsaXRBeGlzfSBzdGF0ZXMgaXQuIHtAbGluayBmaWx0ZXJTdG9wc30gdGhlbiBkb2VzIHRoZSB3aG9sZVxuICogY29tcG9zaXRpb24g4oCUIGNoZWNrIHRoZSBzaGFwZSwga2VlcCB3aGF0IHRoZSBjYWxsZXIga2VlcHMsIFJFLVBBUlRJVElPTiB0aGVcbiAqIGxvZyBzbyB0aGUgZHJvcHBlZCBzdGFnZXMnIGNvbW1pdHMgYXJlIHN0aWxsIGZvbGRlZCBzb21ld2hlcmUsIGFuZCBtYXJrIHRoZVxuICogYCdzdGFydCdgIGJvb2tlbmQgYXMgY2FycnlpbmcgYSBwcm9sb2d1ZSDigJQgYmVjYXVzZSBnZXR0aW5nIHRoZVxuICogcmUtcGFydGl0aW9uaW5nIHJpZ2h0IGJ5IGhhbmQgaXMgdGhlIG90aGVyIHRoaW5nIGV2ZXJ5IGNvbXBvc2VyIGhhZCB0b1xuICogcmVkaXNjb3Zlci5cbiAqL1xuXG5pbXBvcnQgdHlwZSB7IEF4aXNTcGxpdCwgU3RvcCwgU3RvcEtpbmQgfSBmcm9tICcuL3R5cGVzLmpzJztcblxuLyoqXG4gKiBTcGxpdCBhIHN0cmF0ZWd5J3Mgc3RvcHMgaW50byBgeyBzdGFydCwgc3RhZ2VzLCBlbmQgfWAsIG9yIHNheSB3aHkgaXQgY2Fubm90LlxuICpcbiAqIFRIRSBJTlZBUklBTlQsIHN0YXRlZCBvbmNlOiBmb3IgYSBub24tRU1QVFkgbG9nLCBgY29tbWl0U3RvcHNgIHJldHVybnMgYXRcbiAqIGxlYXN0IHRoZSB0d28gYm9va2VuZHMsIGAnc3RhcnQnYCBmaXJzdCBhbmQgYCdlbmQnYCBsYXN0LCB3aXRoIG9uZSBzdG9wIHBlclxuICogZXhlY3V0ZWQgc3RhZ2UgaW4gZXhlY3V0aW9uIG9yZGVyIGJldHdlZW4gdGhlbS4gRm9yIGFuIEVNUFRZIGxvZyBpdCByZXR1cm5zXG4gKiBgW11gIOKAlCBubyBib29rZW5kcyBhcm91bmQgbm90aGluZywgYmVjYXVzZSBhIGN1cnNvciB3aXRoIG5vd2hlcmUgdG8gc3RhbmRcbiAqIHNob3VsZCBzYXkgYHJlYXNvbjogJ2VtcHR5J2AgcmF0aGVyIHRoYW4gb2ZmZXIgdHdvIHBvc2l0aW9ucyB0aGF0IGFyZSB0aGVcbiAqIHNhbWUgcG9zaXRpb24uXG4gKlxuICogVGhlIHR3byByZWZ1c2FscyBhcmUgZGlmZmVyZW50IGZhY3RzIGFuZCBtdXN0IG5vdCBiZSBjb2xsYXBzZWQ6IGAnZW1wdHknYFxuICogbWVhbnMgdGhlIHJ1biBjb21taXR0ZWQgbm90aGluZywgYCdub3QtYm9va2VuZGVkJ2AgbWVhbnMgYSBzdHJhdGVneSBicm9rZVxuICogdGhlIGNvbnRyYWN0LiBBIGNvbXBvc2VyIHRoYXQgdHJlYXRzIHRoZW0gYWxpa2UgcmVwb3J0cyBhIGJyb2tlbiBzdHJhdGVneSBhc1xuICogYW4gZW1wdHkgcnVuLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBpbXBvcnQgeyBjb21taXRTdG9wcywgc3BsaXRBeGlzIH0gZnJvbSAnZm9vdHByaW50anMvdHJhY2UnO1xuICpcbiAqIGNvbnN0IGF4aXMgPSBzcGxpdEF4aXMoY29tbWl0U3RvcHMoc25hcHNob3QuY29tbWl0TG9nLCBzbmFwc2hvdC5leGVjdXRpb25UcmVlKSk7XG4gKiBpZiAoYXhpcy5vaykge1xuICogICBheGlzLnN0YXJ0LmNvbW1pdElkeDsgICAgICAgICAgLy8gLTEg4oCUIHRoZSBmb2xkIGJhc2VcbiAqICAgYXhpcy5zdGFnZXMubWFwKChzKSA9PiBzLmxhYmVsKTtcbiAqICAgYXhpcy5lbmQubGFzdENvbW1pdElkeDsgICAgICAgIC8vIHRoZSBsYXN0IGJ1bmRsZSBpbiB0aGUgbG9nXG4gKiB9IGVsc2Uge1xuICogICBheGlzLnJlYXNvbjsgICAgICAgICAgICAgICAgICAgLy8gJ2VtcHR5JyB8ICdub3QtYm9va2VuZGVkJ1xuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzcGxpdEF4aXM8VE1ldGEgPSB1bmtub3duPihzdG9wczogcmVhZG9ubHkgU3RvcDxUTWV0YT5bXSk6IEF4aXNTcGxpdDxUTWV0YT4ge1xuICBjb25zdCBraW5kczogcmVhZG9ubHkgU3RvcEtpbmRbXSA9IE9iamVjdC5mcmVlemUoc3RvcHMubWFwKChzdG9wKSA9PiBzdG9wLmtpbmQpKTtcbiAgaWYgKHN0b3BzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIHsgb2s6IGZhbHNlLCByZWFzb246ICdlbXB0eScsIGtpbmRzIH07XG4gIGNvbnN0IHN0YXJ0ID0gc3RvcHNbMF07XG4gIGNvbnN0IGVuZCA9IHN0b3BzW3N0b3BzLmxlbmd0aCAtIDFdO1xuICBpZiAoc3RhcnQua2luZCAhPT0gJ3N0YXJ0JyB8fCBlbmQua2luZCAhPT0gJ2VuZCcgfHwgc3RvcHMubGVuZ3RoIDwgMikge1xuICAgIHJldHVybiB7IG9rOiBmYWxzZSwgcmVhc29uOiAnbm90LWJvb2tlbmRlZCcsIGtpbmRzIH07XG4gIH1cbiAgcmV0dXJuIHsgb2s6IHRydWUsIHN0YXJ0LCBzdGFnZXM6IE9iamVjdC5mcmVlemUoc3RvcHMuc2xpY2UoMSwgLTEpKSwgZW5kIH07XG59XG5cbi8qKlxuICogV2hhdCB7QGxpbmsgZmlsdGVyU3RvcHN9IGRvZXMgd2l0aCBvbmUgc3RvcDogZHJvcCBpdCwga2VlcCBpdCwgb3Iga2VlcCBpdFxuICogY2FycnlpbmcgdGhlIHN0cmF0ZWd5J3Mgb3duIGxhYmVsIGFuZCB2b2NhYnVsYXJ5LlxuICpcbiAqIGBmYWxzZWAgLyBgbnVsbGAgLyBgdW5kZWZpbmVkYCBkcm9wLiBgdHJ1ZWAga2VlcHMgaXQgdW5jaGFuZ2VkLiBBbiBvYmplY3RcbiAqIGtlZXBzIGl0IGFuZCBvdmVycmlkZXMgYGxhYmVsYCBhbmQvb3Igc2V0cyBgbWV0YWAg4oCUIHRoZSBzdHJhdGVneSdzIG93blxuICogY2xhc3NpZmljYXRpb24sIHRyYXZlbGxpbmcgT04gdGhlIHN0b3AgaW5zdGVhZCBvZiBiZWluZyByZS1kZXJpdmVkIGZyb21cbiAqIGBydW50aW1lU3RhZ2VJZGAgYXQgZXZlcnkgcmVhZC5cbiAqL1xuZXhwb3J0IHR5cGUgU3RvcEZpbHRlcjxUTWV0YT4gPSBib29sZWFuIHwgbnVsbCB8IHVuZGVmaW5lZCB8IHsgcmVhZG9ubHkgbGFiZWw/OiBzdHJpbmc7IHJlYWRvbmx5IG1ldGE/OiBUTWV0YSB9O1xuXG4vKipcbiAqIGBzdG9wYCByZXR5cGVkIHRvIHRoZSBPVVRQVVQgdm9jYWJ1bGFyeSwgd2l0aCBhbnkgbWV0YSBpdCBhbHJlYWR5IGNhcnJpZWRcbiAqIGxlZnQgYmVoaW5kLiBUaGUgaW5wdXQgYXhpcyBtYXkgaXRzZWxmIGJlIGEgZmlsdGVyZWQgb25lIChhIEJlYXQgYXhpcyBiZWluZ1xuICogbmFycm93ZWQgaW50byBhIFRhZyBheGlzKSwgYW5kIGEgYHRydWVgIGRlY2lzaW9uIGtlZXBzIHRoZSBTVE9QLCBub3QgdGhlXG4gKiBvdGhlciBzdHJhdGVneSdzIGNsYXNzaWZpY2F0aW9uOiBhIGBTdG9wPFRhZz5gIHdob3NlIGBtZXRhYCBpcyBhIEJlYXQgd291bGRcbiAqIGJlIGEgbGllIHRoZSB0eXBlIGNvdWxkIG5vdCBjYXRjaC4gT25seSB0aGUgZGVjaXNpb24gbWF5IHN1cHBseSBhIG1ldGEuXG4gKi9cbmZ1bmN0aW9uIHJldHlwZWQ8VE1ldGE+KHN0b3A6IFN0b3A8dW5rbm93bj4pOiBTdG9wPFRNZXRhPiB7XG4gIGlmIChzdG9wLm1ldGEgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHN0b3AgYXMgU3RvcDxUTWV0YT47XG4gIGNvbnN0IG91dDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7fTtcbiAgY29uc3QgZmllbGRzID0gc3RvcCBhcyB1bmtub3duIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhmaWVsZHMpKSBpZiAoa2V5ICE9PSAnbWV0YScpIG91dFtrZXldID0gZmllbGRzW2tleV07XG4gIHJldHVybiBvdXQgYXMgdW5rbm93biBhcyBTdG9wPFRNZXRhPjtcbn1cblxuLyoqXG4gKiBCdWlsZCBhIEZJTFRFUklORyBzdHJhdGVneSdzIGF4aXMgb3V0IG9mIGFub3RoZXIgc3RyYXRlZ3kncyBzdG9wcy5cbiAqXG4gKiBUaGUgcnVsZSwgaW4gb25lIHNlbnRlbmNlOiBrZWVwIHRoZSBzdGFnZXMgYGtlZXBgIHJlY29nbmlzZXMsIGFuZCBnaXZlIHRoZVxuICogc3Vydml2b3JzIHRoZSBsb2cgYmFjay5cbiAqXG4gKiAqKk1ldGEgaXMgdGhlIGRlY2lzaW9uJ3MsIG5ldmVyIGluaGVyaXRlZC4qKiBUaGUgaW5wdXQgbWF5IGFscmVhZHkgYmUgYVxuICogZmlsdGVyZWQgYXhpcyBjYXJyeWluZyBhbm90aGVyIHN0cmF0ZWd5J3MgYG1ldGFgOyBhIGB0cnVlYCAob3IgYSBtZXRhLWxlc3NcbiAqIG9iamVjdCkga2VlcHMgdGhlIHN0b3AgYW5kIERST1BTIHRoYXQgbWV0YSwgc28gYSBgU3RvcDxUTWV0YT5gIG5ldmVyIGNhcnJpZXNcbiAqIGEgdmFsdWUgb2Ygc29tZSBvdGhlciB0eXBlIHVuZGVyIGBUTWV0YWAuIFRoZSBib29rZW5kcyBjYXJyeSBub25lIGVpdGhlci5cbiAqXG4gKiAqKlRoZSBzdXJ2aXZvcnMgcmUtcGFydGl0aW9uIHRoZSBsb2cuKiogQSBkcm9wcGVkIHN0YWdlJ3MgY29tbWl0cyBzdGlsbFxuICogaGFwcGVuZWQsIHNvIHRoZXkgZm9sZCBpbnRvIHRoZSBzdG9wIHRoYXQgUFJFQ0VERVMgdGhlbTogZXZlcnkga2VwdCBzdG9wJ3NcbiAqIGBsYXN0Q29tbWl0SWR4YCBydW5zIHRvIGp1c3QgYmVmb3JlIHRoZSBuZXh0IGtlcHQgc3RvcCBiZWdpbnMuIE5vdGhpbmcgaXNcbiAqIG9ycGhhbmVkIGFuZCBgc3RhdGVBdChzdG9wKWAgc3RheXMgXCJ0aGUgc3RhdGUgdGhhdCBleGlzdGVkIHdoZW4gdGhlIG5leHRcbiAqIGtlcHQgc3RhZ2Ugc3RhcnRlZFwiLlxuICpcbiAqICoqV2hhdCB0aGF0IGNvc3RzIGAnc3RhcnQnYCwgc2FpZCBvdXQgbG91ZC4qKiBUaGUgY29tbWl0cyBiZWZvcmUgdGhlIGZpcnN0XG4gKiBzdXJ2aXZvciBoYXZlIG5vd2hlcmUgZWxzZSB0byBnbywgc28gYCdzdGFydCdgIGFic29yYnMgdGhlbTogaXRzIGZvbGQgaXMgdGhlXG4gKiBydW4ncyBiYXNlIFBMVVMgdGhhdCBwcm9sb2d1ZSDigJQgdGhlIHN0YXRlIHRoZSBmaXJzdCBzdG9wIFJFQUQsIG5vdCB0aGUgcmF3XG4gKiBiYXNlLiBUaGUgcmV0dXJuZWQgc3RhcnQgdGhlcmVmb3JlIGNhcnJpZXMgYHByb2xvZ3VlOiB0cnVlYCB3aGVuZXZlciBpdFxuICogYWN0dWFsbHkgYWJzb3JiZWQgYSBzdGFnZSwgYW5kIGEgcmVuZGVyZXIgdGhhdCBtZWFucyBcImJlZm9yZSBhbnl0aGluZyByYW5cIlxuICogY2hlY2tzIGBraW5kID09PSAnc3RhcnQnICYmICFwcm9sb2d1ZWAuIFRoYXQgZmxhZyBpcyB0aGUgd2hvbGUgcmVhc29uIHRoaXNcbiAqIGhlbHBlciBleGlzdHMgcmF0aGVyIHRoYW4gYSBgLmZpbHRlcigpYCBjYWxsLlxuICpcbiAqICoqQSBsb2cgd2l0aCBub3RoaW5nIGtlcHQqKiB5aWVsZHMgdGhlIHR3byBib29rZW5kcyBhbmQgbm90aGluZyBiZXR3ZWVuXG4gKiB0aGVtOiBgJ3N0YXJ0J2AgZm9sZHMgdGhlIHdob2xlIGxvZywgYCdlbmQnYCBmb2xkcyB0aGUgd2hvbGUgbG9nLCBhbmRcbiAqIGBqdW1wVG9gIG9uIGFueSBzdGFnZSBpZCByZWZ1c2VzIHdpdGggYHJlYXNvbjogJ21pc3MnYC4gQW4gYXhpcyB3aXRoIG5vd2hlcmVcbiAqIG1lYW5pbmdmdWwgdG8gc3RhbmQg4oCUIHdoaWNoIGlzIHRoZSB0cnV0aGZ1bCBzaGFwZSBmb3IgYSBydW4gdGhpcyBzdHJhdGVneVxuICogcmVjb2duaXNlcyBub3RoaW5nIGluLCBhbmQgTk9UIHRoZSBgW11gIHRoYXQgc2F5cyB0aGUgbG9nIHdhcyBlbXB0eS5cbiAqXG4gKiBAdGhyb3dzIHdoZW4gYHN0b3BzYCBpcyBub24tZW1wdHkgYnV0IG5vdCBib29rZW5kZWQg4oCUIHNlZSB7QGxpbmsgc3BsaXRBeGlzfS5cbiAqICAgT25seSBhIHN0cmF0ZWd5IGNhbiBjYXVzZSB0aGF0OyBhIHJ1biBjYW5ub3QsIHNvIGl0IGlzIGEgY29udHJhY3QgZXJyb3JcbiAqICAgYW5kIG5vdCBhIGNvbmRpdGlvbiB0byBmb2xkIGludG8gdGhlIGRhdGEuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGltcG9ydCB7IGNvbW1pdFN0b3BzLCBmaWx0ZXJTdG9wcyB9IGZyb20gJ2Zvb3RwcmludGpzL3RyYWNlJztcbiAqIGltcG9ydCB0eXBlIHsgU3RvcCwgVGltZVRyYXZlbFN0cmF0ZWd5IH0gZnJvbSAnZm9vdHByaW50anMvdHJhY2UnO1xuICpcbiAqIHR5cGUgTWlsZXN0b25lID0geyBraW5kOiAnbGxtLXR1cm4nIHwgJ3Rvb2wtY2FsbCc7IGxhYmVsOiBzdHJpbmcgfTtcbiAqIGRlY2xhcmUgZnVuY3Rpb24gbWlsZXN0b25lRm9yKHJ1bnRpbWVTdGFnZUlkOiBzdHJpbmcpOiBNaWxlc3RvbmUgfCBudWxsO1xuICpcbiAqIGNvbnN0IG1pbGVzdG9uZVN0b3BzOiBUaW1lVHJhdmVsU3RyYXRlZ3k8TWlsZXN0b25lPiA9IHtcbiAqICAgc3RvcHNGb3I6IChsb2csIHRyZWUpID0+XG4gKiAgICAgZmlsdGVyU3RvcHM8TWlsZXN0b25lPihjb21taXRTdG9wcyhsb2csIHRyZWUpLCAoc3RvcCkgPT4ge1xuICogICAgICAgY29uc3QgbSA9IG1pbGVzdG9uZUZvcihzdG9wLnJ1bnRpbWVTdGFnZUlkKTtcbiAqICAgICAgIHJldHVybiBtID8geyBsYWJlbDogbS5sYWJlbCwgbWV0YTogbSB9IDogbnVsbDtcbiAqICAgICB9KSxcbiAqIH07XG4gKlxuICogY29uc3QgY3Vyc29yID0gdGltZVRyYXZlbChzbmFwc2hvdCwgeyBzdHJhdGVneTogbWlsZXN0b25lU3RvcHMgfSk7XG4gKiBjdXJzb3IuYXQoKT8ubWV0YT8ua2luZDsgICAgICAgIC8vICdsbG0tdHVybicg4oCUIG5vIHJlLWRlcml2YXRpb25cbiAqIGN1cnNvci5zdG9wc1swXS5wcm9sb2d1ZTsgICAgICAgLy8gdHJ1ZSB3aGVuIHN0YWdlcyByYW4gYmVmb3JlIHRoZSBmaXJzdCB0dXJuXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZpbHRlclN0b3BzPFRNZXRhID0gdW5rbm93bj4oXG4gIHN0b3BzOiByZWFkb25seSBTdG9wPHVua25vd24+W10sXG4gIGtlZXA6IChzdG9wOiBTdG9wPHVua25vd24+KSA9PiBTdG9wRmlsdGVyPFRNZXRhPixcbik6IFN0b3A8VE1ldGE+W10ge1xuICBjb25zdCBheGlzID0gc3BsaXRBeGlzKHN0b3BzKTtcbiAgaWYgKCFheGlzLm9rKSB7XG4gICAgaWYgKGF4aXMucmVhc29uID09PSAnZW1wdHknKSByZXR1cm4gW107XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgJ2ZpbHRlclN0b3BzOiBleHBlY3RlZCBhIGJvb2tlbmRlZCBheGlzIOKAlCBbc3RhcnQsIOKApnN0YWdlcywgZW5kXSDigJQgZ290IGtpbmRzICcgK1xuICAgICAgICBgWyR7YXhpcy5raW5kcy5qb2luKCcsICcpfV0uIE9ubHkgYSBzdHJhdGVneSBjYW4gcHJvZHVjZSB0aGF0IHNoYXBlOyBhIHJ1biBjYW5ub3QuYCxcbiAgICApO1xuICB9XG5cbiAgY29uc3Qga2VwdDogeyBzdG9wOiBTdG9wPHVua25vd24+OyBsYWJlbD86IHN0cmluZzsgbWV0YT86IFRNZXRhIH1bXSA9IFtdO1xuICBmb3IgKGNvbnN0IHN0b3Agb2YgYXhpcy5zdGFnZXMpIHtcbiAgICBjb25zdCBkZWNpc2lvbiA9IGtlZXAoc3RvcCk7XG4gICAgaWYgKCFkZWNpc2lvbikgY29udGludWU7XG4gICAgaWYgKGRlY2lzaW9uID09PSB0cnVlKSBrZXB0LnB1c2goeyBzdG9wIH0pO1xuICAgIGVsc2Uga2VwdC5wdXNoKHsgc3RvcCwgbGFiZWw6IGRlY2lzaW9uLmxhYmVsLCBtZXRhOiBkZWNpc2lvbi5tZXRhIH0pO1xuICB9XG5cbiAgLy8gVGhlIGxvZydzIGxhc3QgaW5kZXgsIHRha2VuIGZyb20gdGhlIGAnZW5kJ2AgYm9va2VuZCByYXRoZXIgdGhhbiBhIGxlbmd0aDpcbiAgLy8gYGVuZGAgaXMgdGhlIG9uZSBzdG9wIGd1YXJhbnRlZWQgdG8gZm9sZCB0aGUgd2hvbGUgbG9nLCBhbmQgdGhpcyBmdW5jdGlvblxuICAvLyBpcyBuZXZlciBoYW5kZWQgdGhlIGxvZyBpdHNlbGYuXG4gIGNvbnN0IGxhc3RJZHggPSBheGlzLmVuZC5sYXN0Q29tbWl0SWR4O1xuICBjb25zdCBmaXJzdCA9IGtlcHRbMF07XG4gIGNvbnN0IG91dDogU3RvcDxUTWV0YT5bXSA9IFtcbiAgICB7XG4gICAgICAuLi5yZXR5cGVkPFRNZXRhPihheGlzLnN0YXJ0KSxcbiAgICAgIHN0ZXA6IDAsXG4gICAgICBsYXN0Q29tbWl0SWR4OiBmaXJzdCA/IGZpcnN0LnN0b3AuY29tbWl0SWR4IC0gMSA6IGxhc3RJZHgsXG4gICAgICAvLyBPbmx5IHdoZW4gYSBTVEFHRSB3YXMgYWN0dWFsbHkgYWJzb3JiZWQuIEFuIGF4aXMgdGhhdCBrZXB0IGV2ZXJ5dGhpbmdcbiAgICAgIC8vIGhhcyB0aGUgc2FtZSBzdGFydCBpdCBhbHdheXMgaGFkLCBhbmQgc2F5cyBub3RoaW5nIGl0IG5lZWQgbm90IHNheS5cbiAgICAgIC4uLihmaXJzdCAmJiBmaXJzdC5zdG9wLnN0ZXAgPiAxID8geyBwcm9sb2d1ZTogdHJ1ZSBhcyBjb25zdCB9IDoge30pLFxuICAgICAgLi4uKCFmaXJzdCAmJiBheGlzLnN0YWdlcy5sZW5ndGggPiAwID8geyBwcm9sb2d1ZTogdHJ1ZSBhcyBjb25zdCB9IDoge30pLFxuICAgIH0sXG4gIF07XG5cbiAgZm9yIChjb25zdCBbaSwgcm93XSBvZiBrZXB0LmVudHJpZXMoKSkge1xuICAgIGNvbnN0IG5leHQgPSBrZXB0W2kgKyAxXTtcbiAgICBvdXQucHVzaCh7XG4gICAgICAuLi5yZXR5cGVkPFRNZXRhPihyb3cuc3RvcCksXG4gICAgICBzdGVwOiBvdXQubGVuZ3RoLFxuICAgICAgbGFzdENvbW1pdElkeDogbmV4dCA/IG5leHQuc3RvcC5jb21taXRJZHggLSAxIDogbGFzdElkeCxcbiAgICAgIC4uLihyb3cubGFiZWwgIT09IHVuZGVmaW5lZCA/IHsgbGFiZWw6IHJvdy5sYWJlbCB9IDoge30pLFxuICAgICAgLi4uKHJvdy5tZXRhICE9PSB1bmRlZmluZWQgPyB7IG1ldGE6IHJvdy5tZXRhIH0gOiB7fSksXG4gICAgfSk7XG4gIH1cblxuICBvdXQucHVzaCh7IC4uLnJldHlwZWQ8VE1ldGE+KGF4aXMuZW5kKSwgc3RlcDogb3V0Lmxlbmd0aCB9KTtcbiAgcmV0dXJuIG91dDtcbn1cbiJdfQ==
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* bundles.ts — reading a log whose rows are not typed yet.
|
|
4
|
-
*
|
|
5
|
-
* WHY THIS FILE EXISTS. A LIVE snapshot hands time travel real
|
|
6
|
-
* {@link CommitBundle}s. A STORED recording hands it parsed JSON, and a
|
|
7
|
-
* careful consumer will not claim that what came back off disk is a
|
|
8
|
-
* `CommitBundle` — so it either casts (a lie with a comment on it) or cannot
|
|
9
|
-
* call the library at all. Since 9.18.0 the source takes `readonly unknown[]`
|
|
10
|
-
* and the narrowing happens here, per row, at the one place that actually
|
|
11
|
-
* reads one.
|
|
12
|
-
*
|
|
13
|
-
* A row that is not a bundle becomes a GAP rather than an exception: it KEEPS
|
|
14
|
-
* ITS INDEX — so every `commitIdx` in the axis still addresses the same
|
|
15
|
-
* position — contributes no state, gets no stop, and is reported with its
|
|
16
|
-
* index and a reason. One corrupt row in a stored recording loses that row,
|
|
17
|
-
* not the recording.
|
|
18
|
-
*/
|
|
19
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.readLog = exports.isCommitBundle = exports.bundleRefusal = exports.readTree = exports.isPlainish = void 0;
|
|
21
|
-
const verbs_js_1 = require("../memory/verbs.js");
|
|
22
|
-
/**
|
|
23
|
-
* The stand-in a gap leaves at its index: a commit that belongs to no stage
|
|
24
|
-
* and carries nothing.
|
|
25
|
-
*
|
|
26
|
-
* It is NOT invented evidence — every field is the empty value, and an id-less
|
|
27
|
-
* bundle is a shape the log already has (a root-context commit made before any
|
|
28
|
-
* stage ran). `commitStops` gives it no stop for exactly that reason, the fold
|
|
29
|
-
* folds nothing from it, and `changedSince` reads no keys off it. What it does
|
|
30
|
-
* is hold the index, so the arithmetic downstream never has to know.
|
|
31
|
-
*/
|
|
32
|
-
const GAP_BUNDLE = Object.freeze({
|
|
33
|
-
stage: '',
|
|
34
|
-
stageId: '',
|
|
35
|
-
runtimeStageId: '',
|
|
36
|
-
trace: Object.freeze([]),
|
|
37
|
-
redactedPaths: Object.freeze([]),
|
|
38
|
-
overwrite: Object.freeze({}),
|
|
39
|
-
updates: Object.freeze({}),
|
|
40
|
-
});
|
|
41
|
-
/** A plain object — not null, not an array, not a primitive. */
|
|
42
|
-
function isPlainish(value) {
|
|
43
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
44
|
-
}
|
|
45
|
-
exports.isPlainish = isPlainish;
|
|
46
|
-
/**
|
|
47
|
-
* Read a source's `executionTree` as an {@link ExecutionTree}, or as absent.
|
|
48
|
-
*
|
|
49
|
-
* The tree is only ever WALKED for mount ids (`subflowId` + `runtimeStageId`
|
|
50
|
-
* on each node), so the honest narrowing a reader can do is "a plain object";
|
|
51
|
-
* anything else — a stored field that came back as a string, a number, an
|
|
52
|
-
* array — is read as no tree at all, which sends `commitStops` down the same
|
|
53
|
-
* shape-heuristic path a log handed over without its tree already takes.
|
|
54
|
-
*/
|
|
55
|
-
function readTree(value) {
|
|
56
|
-
return isPlainish(value) ? value : undefined;
|
|
57
|
-
}
|
|
58
|
-
exports.readTree = readTree;
|
|
59
|
-
/**
|
|
60
|
-
* Why `row` cannot be read as a commit bundle, or `undefined` when it can.
|
|
61
|
-
*
|
|
62
|
-
* DELIBERATELY LENIENT — but exactly as lenient as the readers are. It checks
|
|
63
|
-
* what the fold, the axis and `changedSince` actually touch:
|
|
64
|
-
*
|
|
65
|
-
* - `runtimeStageId` must be a string — the axis keys on it.
|
|
66
|
-
* - `trace` must be an ARRAY, and it must be PRESENT. It is the one field
|
|
67
|
-
* every reader WALKS (`applySmartMerge` iterates it verb by verb;
|
|
68
|
-
* `changedSince` reads its paths), so a row without one is not a bundle the
|
|
69
|
-
* fold can survive — it is the crash a gap exists to prevent. `CommitBundle`
|
|
70
|
-
* declares it required, so no live log is affected.
|
|
71
|
-
* - `updates` / `overwrite`, when present, must be plain objects. They are
|
|
72
|
-
* read only AT THE PATHS THE TRACE NAMES, so an absent one is harmless and
|
|
73
|
-
* is tolerated, exactly as the fold tolerates an absent `redactedPaths`.
|
|
74
|
-
*
|
|
75
|
-
* Being stricter than that — demanding `stage`, `stageId`, `idx` — would
|
|
76
|
-
* reject hand-built logs that have folded correctly since 9.17.0, which is a
|
|
77
|
-
* compatibility break dressed up as validation.
|
|
78
|
-
*/
|
|
79
|
-
function bundleRefusal(row) {
|
|
80
|
-
if (!isPlainish(row)) {
|
|
81
|
-
return `not an object (${row === null ? 'null' : Array.isArray(row) ? 'array' : typeof row})`;
|
|
82
|
-
}
|
|
83
|
-
if (typeof row.runtimeStageId !== 'string') {
|
|
84
|
-
return `runtimeStageId is ${row.runtimeStageId === undefined ? 'missing' : `a ${typeof row.runtimeStageId}`}, not a string`;
|
|
85
|
-
}
|
|
86
|
-
if (!Array.isArray(row.trace)) {
|
|
87
|
-
return `trace is ${row.trace === undefined ? 'missing' : `a ${typeof row.trace}`}, not an array`;
|
|
88
|
-
}
|
|
89
|
-
if (row.updates !== undefined && !isPlainish(row.updates))
|
|
90
|
-
return 'updates is not a plain object';
|
|
91
|
-
if (row.overwrite !== undefined && !isPlainish(row.overwrite))
|
|
92
|
-
return 'overwrite is not a plain object';
|
|
93
|
-
// The four verbs are the contract (9.27.0). The replay's switch used to
|
|
94
|
-
// treat anything else as `merge` — a silent coercion of a row a foreign
|
|
95
|
-
// producer got wrong; the readers now refuse it (`UnknownVerbError`), and
|
|
96
|
-
// this reader turns the same refusal into a gap that says which row.
|
|
97
|
-
for (let i = 0; i < row.trace.length; i++) {
|
|
98
|
-
const entry = row.trace[i];
|
|
99
|
-
const verb = isPlainish(entry) ? entry.verb : undefined;
|
|
100
|
-
if (!(0, verbs_js_1.isVerb)(verb)) {
|
|
101
|
-
return `trace[${i}].verb is ${verb === undefined ? 'missing' : JSON.stringify(verb)}, not ${verbs_js_1.VERBS.join(' | ')}`;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
return undefined;
|
|
105
|
-
}
|
|
106
|
-
exports.bundleRefusal = bundleRefusal;
|
|
107
|
-
/** `true` when `row` can be read as a {@link CommitBundle}. */
|
|
108
|
-
function isCommitBundle(row) {
|
|
109
|
-
return bundleRefusal(row) === undefined;
|
|
110
|
-
}
|
|
111
|
-
exports.isCommitBundle = isCommitBundle;
|
|
112
|
-
/** Nothing to read — shared, so the clean path allocates nothing extra. */
|
|
113
|
-
const NO_GAPS = Object.freeze([]);
|
|
114
|
-
/**
|
|
115
|
-
* Read an unvalidated array as a commit log.
|
|
116
|
-
*
|
|
117
|
-
* The clean case (a live snapshot, or a stored recording that round-tripped
|
|
118
|
-
* intact) returns the SAME array reference and no gaps: nothing is copied,
|
|
119
|
-
* nothing is allocated, and the fold behaves byte for byte as it did in
|
|
120
|
-
* 9.17.0. Only a log with a refused row is rebuilt, and only to keep the
|
|
121
|
-
* indices aligned.
|
|
122
|
-
*
|
|
123
|
-
* @example
|
|
124
|
-
* ```typescript
|
|
125
|
-
* const { log, gaps } = readLog(JSON.parse(stored).commitLog);
|
|
126
|
-
* gaps; // [{ index: 3, reason: 'not an object (null)' }]
|
|
127
|
-
* ```
|
|
128
|
-
*/
|
|
129
|
-
function readLog(raw) {
|
|
130
|
-
if (!raw || raw.length === 0)
|
|
131
|
-
return { log: [], gaps: NO_GAPS };
|
|
132
|
-
let gaps;
|
|
133
|
-
for (let i = 0; i < raw.length; i++) {
|
|
134
|
-
const reason = bundleRefusal(raw[i]);
|
|
135
|
-
if (reason !== undefined)
|
|
136
|
-
(gaps ??= []).push({ index: i, reason });
|
|
137
|
-
}
|
|
138
|
-
if (!gaps)
|
|
139
|
-
return { log: raw, gaps: NO_GAPS };
|
|
140
|
-
const log = raw.map((row) => (isCommitBundle(row) ? row : GAP_BUNDLE));
|
|
141
|
-
return { log, gaps: Object.freeze(gaps) };
|
|
142
|
-
}
|
|
143
|
-
exports.readLog = readLog;
|
|
144
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVuZGxlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvdGltZS10cmF2ZWwvYnVuZGxlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQkc7OztBQUdILGlEQUFtRDtBQUduRDs7Ozs7Ozs7O0dBU0c7QUFDSCxNQUFNLFVBQVUsR0FBaUIsTUFBTSxDQUFDLE1BQU0sQ0FBQztJQUM3QyxLQUFLLEVBQUUsRUFBRTtJQUNULE9BQU8sRUFBRSxFQUFFO0lBQ1gsY0FBYyxFQUFFLEVBQUU7SUFDbEIsS0FBSyxFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFxQztJQUM1RCxhQUFhLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQXdCO0lBQ3ZELFNBQVMsRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztJQUM1QixPQUFPLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7Q0FDM0IsQ0FBQyxDQUFDO0FBRUgsZ0VBQWdFO0FBQ2hFLFNBQWdCLFVBQVUsQ0FBQyxLQUFjO0lBQ3ZDLE9BQU8sT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLEtBQUssS0FBSyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQzlFLENBQUM7QUFGRCxnQ0FFQztBQUVEOzs7Ozs7OztHQVFHO0FBQ0gsU0FBZ0IsUUFBUSxDQUFDLEtBQWM7SUFDckMsT0FBTyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFFLEtBQWtDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztBQUM3RSxDQUFDO0FBRkQsNEJBRUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1CRztBQUNILFNBQWdCLGFBQWEsQ0FBQyxHQUFZO0lBQ3hDLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUNyQixPQUFP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UUFDckMsSUFBSSxNQUFNLEtBQUssU0FBUztZQUFFLENBQUMsSUFBSSxLQUFLLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztJQUNyRSxDQUFDO0lBQ0QsSUFBSSxDQUFDLElBQUk7UUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLEdBQThCLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxDQUFDO0lBRXpFLE1BQU0sR0FBRyxHQUFHLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7SUFDdkUsT0FBTyxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO0FBQzVDLENBQUM7QUFaRCwwQkFZQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogYnVuZGxlcy50cyDigJQgcmVhZGluZyBhIGxvZyB3aG9zZSByb3dzIGFyZSBub3QgdHlwZWQgeWV0LlxuICpcbiAqIFdIWSBUSElTIEZJTEUgRVhJU1RTLiBBIExJVkUgc25hcHNob3QgaGFuZHMgdGltZSB0cmF2ZWwgcmVhbFxuICoge0BsaW5rIENvbW1pdEJ1bmRsZX1zLiBBIFNUT1JFRCByZWNvcmRpbmcgaGFuZHMgaXQgcGFyc2VkIEpTT04sIGFuZCBhXG4gKiBjYXJlZnVsIGNvbnN1bWVyIHdpbGwgbm90IGNsYWltIHRoYXQgd2hhdCBjYW1lIGJhY2sgb2ZmIGRpc2sgaXMgYVxuICogYENvbW1pdEJ1bmRsZWAg4oCUIHNvIGl0IGVpdGhlciBjYXN0cyAoYSBsaWUgd2l0aCBhIGNvbW1lbnQgb24gaXQpIG9yIGNhbm5vdFxuICogY2FsbCB0aGUgbGlicmFyeSBhdCBhbGwuIFNpbmNlIDkuMTguMCB0aGUgc291cmNlIHRha2VzIGByZWFkb25seSB1bmtub3duW11gXG4gKiBhbmQgdGhlIG5hcnJvd2luZyBoYXBwZW5zIGhlcmUsIHBlciByb3csIGF0IHRoZSBvbmUgcGxhY2UgdGhhdCBhY3R1YWxseVxuICogcmVhZHMgb25lLlxuICpcbiAqIEEgcm93IHRoYXQgaXMgbm90IGEgYnVuZGxlIGJlY29tZXMgYSBHQVAgcmF0aGVyIHRoYW4gYW4gZXhjZXB0aW9uOiBpdCBLRUVQU1xuICogSVRTIElOREVYIOKAlCBzbyBldmVyeSBgY29tbWl0SWR4YCBpbiB0aGUgYXhpcyBzdGlsbCBhZGRyZXNzZXMgdGhlIHNhbWVcbiAqIHBvc2l0aW9uIOKAlCBjb250cmlidXRlcyBubyBzdGF0ZSwgZ2V0cyBubyBzdG9wLCBhbmQgaXMgcmVwb3J0ZWQgd2l0aCBpdHNcbiAqIGluZGV4IGFuZCBhIHJlYXNvbi4gT25lIGNvcnJ1cHQgcm93IGluIGEgc3RvcmVkIHJlY29yZGluZyBsb3NlcyB0aGF0IHJvdyxcbiAqIG5vdCB0aGUgcmVjb3JkaW5nLlxuICovXG5cbmltcG9ydCB0eXBlIHsgQ29tbWl0QnVuZGxlLCBFeGVjdXRpb25UcmVlIH0gZnJvbSAnLi4vbWVtb3J5L3R5cGVzLmpzJztcbmltcG9ydCB7IGlzVmVyYiwgVkVSQlMgfSBmcm9tICcuLi9tZW1vcnkvdmVyYnMuanMnO1xuaW1wb3J0IHR5cGUgeyBMb2dHYXAgfSBmcm9tICcuL3R5cGVzLmpzJztcblxuLyoqXG4gKiBUaGUgc3RhbmQtaW4gYSBnYXAgbGVhdmVzIGF0IGl0cyBpbmRleDogYSBjb21taXQgdGhhdCBiZWxvbmdzIHRvIG5vIHN0YWdlXG4gKiBhbmQgY2FycmllcyBub3RoaW5nLlxuICpcbiAqIEl0IGlzIE5PVCBpbnZlbnRlZCBldmlkZW5jZSDigJQgZXZlcnkgZmllbGQgaXMgdGhlIGVtcHR5IHZhbHVlLCBhbmQgYW4gaWQtbGVzc1xuICogYnVuZGxlIGlzIGEgc2hhcGUgdGhlIGxvZyBhbHJlYWR5IGhhcyAoYSByb290LWNvbnRleHQgY29tbWl0IG1hZGUgYmVmb3JlIGFueVxuICogc3RhZ2UgcmFuKS4gYGNvbW1pdFN0b3BzYCBnaXZlcyBpdCBubyBzdG9wIGZvciBleGFjdGx5IHRoYXQgcmVhc29uLCB0aGUgZm9sZFxuICogZm9sZHMgbm90aGluZyBmcm9tIGl0LCBhbmQgYGNoYW5nZWRTaW5jZWAgcmVhZHMgbm8ga2V5cyBvZmYgaXQuIFdoYXQgaXQgZG9lc1xuICogaXMgaG9sZCB0aGUgaW5kZXgsIHNvIHRoZSBhcml0aG1ldGljIGRvd25zdHJlYW0gbmV2ZXIgaGFzIHRvIGtub3cuXG4gKi9cbmNvbnN0IEdBUF9CVU5ETEU6IENvbW1pdEJ1bmRsZSA9IE9iamVjdC5mcmVlemUoe1xuICBzdGFnZTogJycsXG4gIHN0YWdlSWQ6ICcnLFxuICBydW50aW1lU3RhZ2VJZDogJycsXG4gIHRyYWNlOiBPYmplY3QuZnJlZXplKFtdKSBhcyB1bmtub3duIGFzIENvbW1pdEJ1bmRsZVsndHJhY2UnXSxcbiAgcmVkYWN0ZWRQYXRoczogT2JqZWN0LmZyZWV6ZShbXSkgYXMgdW5rbm93biBhcyBzdHJpbmdbXSxcbiAgb3ZlcndyaXRlOiBPYmplY3QuZnJlZXplKHt9KSxcbiAgdXBkYXRlczogT2JqZWN0LmZyZWV6ZSh7fSksXG59KTtcblxuLyoqIEEgcGxhaW4gb2JqZWN0IOKAlCBub3QgbnVsbCwgbm90IGFuIGFycmF5LCBub3QgYSBwcmltaXRpdmUuICovXG5leHBvcnQgZnVuY3Rpb24gaXNQbGFpbmlzaCh2YWx1ZTogdW5rbm93bik6IHZhbHVlIGlzIFJlY29yZDxzdHJpbmcsIHVua25vd24+IHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYgdmFsdWUgIT09IG51bGwgJiYgIUFycmF5LmlzQXJyYXkodmFsdWUpO1xufVxuXG4vKipcbiAqIFJlYWQgYSBzb3VyY2UncyBgZXhlY3V0aW9uVHJlZWAgYXMgYW4ge0BsaW5rIEV4ZWN1dGlvblRyZWV9LCBvciBhcyBhYnNlbnQuXG4gKlxuICogVGhlIHRyZWUgaXMgb25seSBldmVyIFdBTEtFRCBmb3IgbW91bnQgaWRzIChgc3ViZmxvd0lkYCArIGBydW50aW1lU3RhZ2VJZGBcbiAqIG9uIGVhY2ggbm9kZSksIHNvIHRoZSBob25lc3QgbmFycm93aW5nIGEgcmVhZGVyIGNhbiBkbyBpcyBcImEgcGxhaW4gb2JqZWN0XCI7XG4gKiBhbnl0aGluZyBlbHNlIOKAlCBhIHN0b3JlZCBmaWVsZCB0aGF0IGNhbWUgYmFjayBhcyBhIHN0cmluZywgYSBudW1iZXIsIGFuXG4gKiBhcnJheSDigJQgaXMgcmVhZCBhcyBubyB0cmVlIGF0IGFsbCwgd2hpY2ggc2VuZHMgYGNvbW1pdFN0b3BzYCBkb3duIHRoZSBzYW1lXG4gKiBzaGFwZS1oZXVyaXN0aWMgcGF0aCBhIGxvZyBoYW5kZWQgb3ZlciB3aXRob3V0IGl0cyB0cmVlIGFscmVhZHkgdGFrZXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWFkVHJlZSh2YWx1ZTogdW5rbm93bik6IEV4ZWN1dGlvblRyZWUgfCB1bmRlZmluZWQge1xuICByZXR1cm4gaXNQbGFpbmlzaCh2YWx1ZSkgPyAodmFsdWUgYXMgdW5rbm93biBhcyBFeGVjdXRpb25UcmVlKSA6IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBXaHkgYHJvd2AgY2Fubm90IGJlIHJlYWQgYXMgYSBjb21taXQgYnVuZGxlLCBvciBgdW5kZWZpbmVkYCB3aGVuIGl0IGNhbi5cbiAqXG4gKiBERUxJQkVSQVRFTFkgTEVOSUVOVCDigJQgYnV0IGV4YWN0bHkgYXMgbGVuaWVudCBhcyB0aGUgcmVhZGVycyBhcmUuIEl0IGNoZWNrc1xuICogd2hhdCB0aGUgZm9sZCwgdGhlIGF4aXMgYW5kIGBjaGFuZ2VkU2luY2VgIGFjdHVhbGx5IHRvdWNoOlxuICpcbiAqIC0gYHJ1bnRpbWVTdGFnZUlkYCBtdXN0IGJlIGEgc3RyaW5nIOKAlCB0aGUgYXhpcyBrZXlzIG9uIGl0LlxuICogLSBgdHJhY2VgIG11c3QgYmUgYW4gQVJSQVksIGFuZCBpdCBtdXN0IGJlIFBSRVNFTlQuIEl0IGlzIHRoZSBvbmUgZmllbGRcbiAqICAgZXZlcnkgcmVhZGVyIFdBTEtTIChgYXBwbHlTbWFydE1lcmdlYCBpdGVyYXRlcyBpdCB2ZXJiIGJ5IHZlcmI7XG4gKiAgIGBjaGFuZ2VkU2luY2VgIHJlYWRzIGl0cyBwYXRocyksIHNvIGEgcm93IHdpdGhvdXQgb25lIGlzIG5vdCBhIGJ1bmRsZSB0aGVcbiAqICAgZm9sZCBjYW4gc3Vydml2ZSDigJQgaXQgaXMgdGhlIGNyYXNoIGEgZ2FwIGV4aXN0cyB0byBwcmV2ZW50LiBgQ29tbWl0QnVuZGxlYFxuICogICBkZWNsYXJlcyBpdCByZXF1aXJlZCwgc28gbm8gbGl2ZSBsb2cgaXMgYWZmZWN0ZWQuXG4gKiAtIGB1cGRhdGVzYCAvIGBvdmVyd3JpdGVgLCB3aGVuIHByZXNlbnQsIG11c3QgYmUgcGxhaW4gb2JqZWN0cy4gVGhleSBhcmVcbiAqICAgcmVhZCBvbmx5IEFUIFRIRSBQQVRIUyBUSEUgVFJBQ0UgTkFNRVMsIHNvIGFuIGFic2VudCBvbmUgaXMgaGFybWxlc3MgYW5kXG4gKiAgIGlzIHRvbGVyYXRlZCwgZXhhY3RseSBhcyB0aGUgZm9sZCB0b2xlcmF0ZXMgYW4gYWJzZW50IGByZWRhY3RlZFBhdGhzYC5cbiAqXG4gKiBCZWluZyBzdHJpY3RlciB0aGFuIHRoYXQg4oCUIGRlbWFuZGluZyBgc3RhZ2VgLCBgc3RhZ2VJZGAsIGBpZHhgIOKAlCB3b3VsZFxuICogcmVqZWN0IGhhbmQtYnVpbHQgbG9ncyB0aGF0IGhhdmUgZm9sZGVkIGNvcnJlY3RseSBzaW5jZSA5LjE3LjAsIHdoaWNoIGlzIGFcbiAqIGNvbXBhdGliaWxpdHkgYnJlYWsgZHJlc3NlZCB1cCBhcyB2YWxpZGF0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYnVuZGxlUmVmdXNhbChyb3c6IHVua25vd24pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBpZiAoIWlzUGxhaW5pc2gocm93KSkge1xuICAgIHJldHVybiBgbm90IGFuIG9iamVjdCAoJHtyb3cgPT09IG51bGwgPyAnbnVsbCcgOiBBcnJheS5pc0FycmF5KHJvdykgPyAnYXJyYXknIDogdHlwZW9mIHJvd30pYDtcbiAgfVxuICBpZiAodHlwZW9mIHJvdy5ydW50aW1lU3RhZ2VJZCAhPT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gYHJ1bnRpbWVTdGFnZUlkIGlzICR7XG4gICAgICByb3cucnVudGltZVN0YWdlSWQgPT09IHVuZGVmaW5lZCA/ICdtaXNzaW5nJyA6IGBhICR7dHlwZW9mIHJvdy5ydW50aW1lU3RhZ2VJZH1gXG4gICAgfSwgbm90IGEgc3RyaW5nYDtcbiAgfVxuICBpZiAoIUFycmF5LmlzQXJyYXkocm93LnRyYWNlKSkge1xuICAgIHJldHVybiBgdHJhY2UgaXMgJHtyb3cudHJhY2UgPT09IHVuZGVmaW5lZCA/ICdtaXNzaW5nJyA6IGBhICR7dHlwZW9mIHJvdy50cmFjZX1gfSwgbm90IGFuIGFycmF5YDtcbiAgfVxuICBpZiAocm93LnVwZGF0ZXMgIT09IHVuZGVmaW5lZCAmJiAhaXNQbGFpbmlzaChyb3cudXBkYXRlcykpIHJldHVybiAndXBkYXRlcyBpcyBub3QgYSBwbGFpbiBvYmplY3QnO1xuICBpZiAocm93Lm92ZXJ3cml0ZSAhPT0gdW5kZWZpbmVkICYmICFpc1BsYWluaXNoKHJvdy5vdmVyd3JpdGUpKSByZXR1cm4gJ292ZXJ3cml0ZSBpcyBub3QgYSBwbGFpbiBvYmplY3QnO1xuICAvLyBUaGUgZm91ciB2ZXJicyBhcmUgdGhlIGNvbnRyYWN0ICg5LjI3LjApLiBUaGUgcmVwbGF5J3Mgc3dpdGNoIHVzZWQgdG9cbiAgLy8gdHJlYXQgYW55dGhpbmcgZWxzZSBhcyBgbWVyZ2VgIOKAlCBhIHNpbGVudCBjb2VyY2lvbiBvZiBhIHJvdyBhIGZvcmVpZ25cbiAgLy8gcHJvZHVjZXIgZ290IHdyb25nOyB0aGUgcmVhZGVycyBub3cgcmVmdXNlIGl0IChgVW5rbm93blZlcmJFcnJvcmApLCBhbmRcbiAgLy8gdGhpcyByZWFkZXIgdHVybnMgdGhlIHNhbWUgcmVmdXNhbCBpbnRvIGEgZ2FwIHRoYXQgc2F5cyB3aGljaCByb3cuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgcm93LnRyYWNlLmxlbmd0aDsgaSsrKSB7XG4gICAgY29uc3QgZW50cnk6IHVua25vd24gPSByb3cudHJhY2VbaV07XG4gICAgY29uc3QgdmVyYiA9IGlzUGxhaW5pc2goZW50cnkpID8gZW50cnkudmVyYiA6IHVuZGVmaW5lZDtcbiAgICBpZiAoIWlzVmVyYih2ZXJiKSkge1xuICAgICAgcmV0dXJuIGB0cmFjZVske2l9XS52ZXJiIGlzICR7dmVyYiA9PT0gdW5kZWZpbmVkID8gJ21pc3NpbmcnIDogSlNPTi5zdHJpbmdpZnkodmVyYil9LCBub3QgJHtWRVJCUy5qb2luKCcgfCAnKX1gO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG4vKiogYHRydWVgIHdoZW4gYHJvd2AgY2FuIGJlIHJlYWQgYXMgYSB7QGxpbmsgQ29tbWl0QnVuZGxlfS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0NvbW1pdEJ1bmRsZShyb3c6IHVua25vd24pOiByb3cgaXMgQ29tbWl0QnVuZGxlIHtcbiAgcmV0dXJuIGJ1bmRsZVJlZnVzYWwocm93KSA9PT0gdW5kZWZpbmVkO1xufVxuXG4vKiogQSBsb2cgcmVhZCByb3cgYnkgcm93OiB0aGUgYnVuZGxlcywgaW5kZXgtYWxpZ25lZCwgcGx1cyB3aGF0IHdhcyByZWZ1c2VkLiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZWFkTG9nIHtcbiAgLyoqIFNhbWUgbGVuZ3RoIGFuZCBvcmRlciBhcyB0aGUgaW5wdXQ7IGEgcmVmdXNlZCByb3cgaG9sZHMgYSBHQVAgc3RhbmQtaW4uICovXG4gIHJlYWRvbmx5IGxvZzogcmVhZG9ubHkgQ29tbWl0QnVuZGxlW107XG4gIC8qKiBUaGUgcmVmdXNlZCByb3dzLCBpbiBpbmRleCBvcmRlci4gRW1wdHkgd2hlbiB0aGUgbG9nIHdhcyBjbGVhbi4gKi9cbiAgcmVhZG9ubHkgZ2FwczogcmVhZG9ubHkgTG9nR2FwW107XG59XG5cbi8qKiBOb3RoaW5nIHRvIHJlYWQg4oCUIHNoYXJlZCwgc28gdGhlIGNsZWFuIHBhdGggYWxsb2NhdGVzIG5vdGhpbmcgZXh0cmEuICovXG5jb25zdCBOT19HQVBTOiByZWFkb25seSBMb2dHYXBbXSA9IE9iamVjdC5mcmVlemUoW10pO1xuXG4vKipcbiAqIFJlYWQgYW4gdW52YWxpZGF0ZWQgYXJyYXkgYXMgYSBjb21taXQgbG9nLlxuICpcbiAqIFRoZSBjbGVhbiBjYXNlIChhIGxpdmUgc25hcHNob3QsIG9yIGEgc3RvcmVkIHJlY29yZGluZyB0aGF0IHJvdW5kLXRyaXBwZWRcbiAqIGludGFjdCkgcmV0dXJucyB0aGUgU0FNRSBhcnJheSByZWZlcmVuY2UgYW5kIG5vIGdhcHM6IG5vdGhpbmcgaXMgY29waWVkLFxuICogbm90aGluZyBpcyBhbGxvY2F0ZWQsIGFuZCB0aGUgZm9sZCBiZWhhdmVzIGJ5dGUgZm9yIGJ5dGUgYXMgaXQgZGlkIGluXG4gKiA5LjE3LjAuIE9ubHkgYSBsb2cgd2l0aCBhIHJlZnVzZWQgcm93IGlzIHJlYnVpbHQsIGFuZCBvbmx5IHRvIGtlZXAgdGhlXG4gKiBpbmRpY2VzIGFsaWduZWQuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IHsgbG9nLCBnYXBzIH0gPSByZWFkTG9nKEpTT04ucGFyc2Uoc3RvcmVkKS5jb21taXRMb2cpO1xuICogZ2FwczsgLy8gW3sgaW5kZXg6IDMsIHJlYXNvbjogJ25vdCBhbiBvYmplY3QgKG51bGwpJyB9XVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWFkTG9nKHJhdzogcmVhZG9ubHkgdW5rbm93bltdIHwgdW5kZWZpbmVkKTogUmVhZExvZyB7XG4gIGlmICghcmF3IHx8IHJhdy5sZW5ndGggPT09IDApIHJldHVybiB7IGxvZzogW10sIGdhcHM6IE5PX0dBUFMgfTtcblxuICBsZXQgZ2FwczogTG9nR2FwW10gfCB1bmRlZmluZWQ7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgcmF3Lmxlbmd0aDsgaSsrKSB7XG4gICAgY29uc3QgcmVhc29uID0gYnVuZGxlUmVmdXNhbChyYXdbaV0pO1xuICAgIGlmIChyZWFzb24gIT09IHVuZGVmaW5lZCkgKGdhcHMgPz89IFtdKS5wdXNoKHsgaW5kZXg6IGksIHJlYXNvbiB9KTtcbiAgfVxuICBpZiAoIWdhcHMpIHJldHVybiB7IGxvZzogcmF3IGFzIHJlYWRvbmx5IENvbW1pdEJ1bmRsZVtdLCBnYXBzOiBOT19HQVBTIH07XG5cbiAgY29uc3QgbG9nID0gcmF3Lm1hcCgocm93KSA9PiAoaXNDb21taXRCdW5kbGUocm93KSA/IHJvdyA6IEdBUF9CVU5ETEUpKTtcbiAgcmV0dXJuIHsgbG9nLCBnYXBzOiBPYmplY3QuZnJlZXplKGdhcHMpIH07XG59XG4iXX0=
|
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* chain.ts — reading a pause/resume as ONE axis.
|
|
4
|
-
*
|
|
5
|
-
* WHY THIS FILE EXISTS. A pause and its resume produce TWO snapshots. On a
|
|
6
|
-
* cross-executor resume (the checkpoint was persisted and a fresh executor
|
|
7
|
-
* picked it up) the second run gets a fresh runtime: its `commitLog` starts at
|
|
8
|
-
* index 0 and holds only the post-resume commits, and its `initialState` is
|
|
9
|
-
* the state at the pause. Two logs, two disjoint axes — so a reader scrubbing
|
|
10
|
-
* a resumed run saw only the second half unless the application had kept the
|
|
11
|
-
* paused snapshot and stitched the halves itself. Every application that
|
|
12
|
-
* pauses would write that stitching, and none of them own the arithmetic.
|
|
13
|
-
*
|
|
14
|
-
* THE HONEST BIT, up front: COMMIT INDICES ARE RUN-LOCAL. There is no global
|
|
15
|
-
* index across a chain and this file does not invent one — `commitIdx` and
|
|
16
|
-
* `lastCommitIdx` keep indexing their own source, and every stop carries the
|
|
17
|
-
* {@link Stop.sourceIdx} they belong to. The cursor's STEPS are what run
|
|
18
|
-
* across the whole chain.
|
|
19
|
-
*
|
|
20
|
-
* AND THE REFUSAL: a chain that is not ordered, or whose legs are not from one
|
|
21
|
-
* lineage, is REFUSED rather than guessed at. The record carries TWO signals
|
|
22
|
-
* and this file reads both:
|
|
23
|
-
*
|
|
24
|
-
* - The execution index the engine stamps into every `runtimeStageId` —
|
|
25
|
-
* globally monotonic per run and, deliberately, NOT reset on resume. So a
|
|
26
|
-
* later leg's first execution index must be past the earlier leg's last, and
|
|
27
|
-
* no stage may appear in two legs. This catches a backwards chain, a fresh
|
|
28
|
-
* run (which restarts at 0) and a same-executor resume (whose one snapshot
|
|
29
|
-
* already holds both halves).
|
|
30
|
-
* - The later leg's `initialState`. On a resume the fresh runtime is seeded
|
|
31
|
-
* from the checkpoint, so that base IS the state at the pause — and the
|
|
32
|
-
* state the earlier legs FOLD TO must deep-equal it. This is what catches a
|
|
33
|
-
* leg from some OTHER lineage whose indices merely happen to be higher: the
|
|
34
|
-
* counters line up by accident, the state never does.
|
|
35
|
-
*
|
|
36
|
-
* A chart identity or a lineage id is NOT on the record, so nothing here
|
|
37
|
-
* pretends to check one. And where the state signal is not on the record
|
|
38
|
-
* either — a leg recorded before 9.17 carries no `initialState`; an earlier
|
|
39
|
-
* leg with no base folds `'log-only'`; a leg with unreadable rows folds an
|
|
40
|
-
* incomplete state — that check is SKIPPED, not faked: the chain then rests on
|
|
41
|
-
* the index checks alone, and every fold's `basis` still says what it stood
|
|
42
|
-
* on. That degradation is documented on `refuseChain`, on `timeTravel`'s
|
|
43
|
-
* `@throws`, and in the README.
|
|
44
|
-
*/
|
|
45
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
-
exports.refuseChain = exports.spanOf = void 0;
|
|
47
|
-
const valueKinds_js_1 = require("../capture/valueKinds.js");
|
|
48
|
-
const runtimeStageId_js_1 = require("../ids/runtimeStageId.js");
|
|
49
|
-
const utils_js_1 = require("../memory/utils.js");
|
|
50
|
-
const stateAt_js_1 = require("./stateAt.js");
|
|
51
|
-
/** The execution-index span of one leg, read off its `runtimeStageId`s. */
|
|
52
|
-
function spanOf(log) {
|
|
53
|
-
let first;
|
|
54
|
-
let last;
|
|
55
|
-
const ids = new Set();
|
|
56
|
-
for (const bundle of log) {
|
|
57
|
-
const id = bundle.runtimeStageId;
|
|
58
|
-
if (!id)
|
|
59
|
-
continue;
|
|
60
|
-
ids.add(id);
|
|
61
|
-
const { executionIndex } = (0, runtimeStageId_js_1.parseRuntimeStageId)(id);
|
|
62
|
-
if (Number.isNaN(executionIndex))
|
|
63
|
-
continue;
|
|
64
|
-
if (first === undefined || executionIndex < first)
|
|
65
|
-
first = executionIndex;
|
|
66
|
-
if (last === undefined || executionIndex > last)
|
|
67
|
-
last = executionIndex;
|
|
68
|
-
}
|
|
69
|
-
return { first, last, ids };
|
|
70
|
-
}
|
|
71
|
-
exports.spanOf = spanOf;
|
|
72
|
-
/**
|
|
73
|
-
* Structural equality of two folded states, ignoring the paths the log was
|
|
74
|
-
* redacted at.
|
|
75
|
-
*
|
|
76
|
-
* The fold reproduces `'REDACTED'` wherever the engine scrubbed a write, while
|
|
77
|
-
* the checkpoint that seeded the resumed leg holds the real value — so those
|
|
78
|
-
* paths CANNOT agree, and are not asked to. Everything else is decided by the
|
|
79
|
-
* ONE equality law (`memory/equality.ts · deepEqual`, every value kind compared
|
|
80
|
-
* as the record holds it; 9.44.2 — this walk had a law of its own, which held
|
|
81
|
-
* any two RegExps, Errors or buffers equal). Both sides are copies of one
|
|
82
|
-
* record, so an opaque value compares as `'copies'`. Only the containers above
|
|
83
|
-
* a redacted path are walked here.
|
|
84
|
-
*/
|
|
85
|
-
function sameState(a, b, redacted, path) {
|
|
86
|
-
if (!redactedBelow(path, redacted))
|
|
87
|
-
return (0, utils_js_1.deepEqual)(a, b, 'copies');
|
|
88
|
-
if (Array.isArray(a) && Array.isArray(b)) {
|
|
89
|
-
if (a.length !== b.length)
|
|
90
|
-
return false;
|
|
91
|
-
return a.every((item, i) => sameState(item, b[i], redacted, path === '' ? String(i) : `${path}${utils_js_1.DELIM}${i}`));
|
|
92
|
-
}
|
|
93
|
-
const plain = (v) => v !== null && typeof v === 'object' && !Array.isArray(v) && (0, valueKinds_js_1.kindOf)(v) === 'plain';
|
|
94
|
-
if (!plain(a) || !plain(b))
|
|
95
|
-
return (0, utils_js_1.deepEqual)(a, b, 'copies');
|
|
96
|
-
const present = (o) => Object.keys(o).filter((k) => o[k] !== undefined);
|
|
97
|
-
const leftKeys = present(a);
|
|
98
|
-
const rightKeys = new Set(present(b));
|
|
99
|
-
if (leftKeys.length !== rightKeys.size || !leftKeys.every((k) => rightKeys.has(k)))
|
|
100
|
-
return false;
|
|
101
|
-
return leftKeys.every((k) => {
|
|
102
|
-
const childPath = path === '' ? k : `${path}${utils_js_1.DELIM}${k}`;
|
|
103
|
-
return redacted.has(childPath) || sameState(a[k], b[k], redacted, childPath);
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
/** Is `path`, or a path below it, one the log was redacted at? */
|
|
107
|
-
function redactedBelow(path, redacted) {
|
|
108
|
-
if (redacted.size === 0)
|
|
109
|
-
return false;
|
|
110
|
-
if (path === '')
|
|
111
|
-
return true;
|
|
112
|
-
for (const r of redacted)
|
|
113
|
-
if (r === path || r.startsWith(`${path}${utils_js_1.DELIM}`))
|
|
114
|
-
return true;
|
|
115
|
-
return false;
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Check that `legs` really are one run read in order, and say why not.
|
|
119
|
-
*
|
|
120
|
-
* Returns the refusal message, or `undefined` when the chain is sound. Three
|
|
121
|
-
* distinct failures, because they are three different mistakes, checked in
|
|
122
|
-
* this order:
|
|
123
|
-
*
|
|
124
|
-
* - REPEATED STAGE — one `runtimeStageId` appears in two legs. Ids are unique
|
|
125
|
-
* within a run, so a repeat means the same execution was recorded twice: a
|
|
126
|
-
* same-executor resume, whose snapshot ALREADY holds the whole log and needs
|
|
127
|
-
* no chaining, is the usual cause.
|
|
128
|
-
* - OUT OF ORDER — a later leg's first execution index is not past the earlier
|
|
129
|
-
* leg's last. Either the sources were handed over backwards, or the second
|
|
130
|
-
* is not a continuation at all (a fresh run restarts the counter at 0, so an
|
|
131
|
-
* unrelated snapshot fails here rather than silently interleaving).
|
|
132
|
-
* - WRONG LINEAGE — leg k's `initialState` is not the state legs 0..k-1 fold
|
|
133
|
-
* to. On a resume the later leg is seeded from the checkpoint, so its base
|
|
134
|
-
* IS the state at the pause; a leg that begins anywhere else is from some
|
|
135
|
-
* other run, however its indices happen to line up.
|
|
136
|
-
*
|
|
137
|
-
* THE LINEAGE CHECK RUNS ONLY WHERE THE RECORD ALLOWS IT, and is skipped —
|
|
138
|
-
* never faked — otherwise: leg k must carry an `initialState` (a recording
|
|
139
|
-
* made before 9.17 has none), and the fold of the legs before it must stand on
|
|
140
|
-
* a real base (`basis: 'initial+log'`) with no unreadable rows (`skipped`
|
|
141
|
-
* absent) — a log-only or gapped fold is not a state a real base may be held
|
|
142
|
-
* against. On such a chain the two index checks are the whole defence, and
|
|
143
|
-
* `foldLegs`' leg rule then CONTINUES the fold across the seam, which is the
|
|
144
|
-
* right state for a real resume and is what `basis` reports. Paths the log
|
|
145
|
-
* was redacted at are excluded from the comparison: the fold holds
|
|
146
|
-
* `'REDACTED'` there and the checkpoint holds the value.
|
|
147
|
-
*/
|
|
148
|
-
function refuseChain(legs) {
|
|
149
|
-
if (legs.length === 0)
|
|
150
|
-
return 'timeTravel: a chain needs at least one source, got an empty array.';
|
|
151
|
-
const spans = legs.map((leg) => spanOf(leg.log));
|
|
152
|
-
const seen = new Map();
|
|
153
|
-
for (const [i, span] of spans.entries()) {
|
|
154
|
-
for (const id of span.ids) {
|
|
155
|
-
const earlier = seen.get(id);
|
|
156
|
-
if (earlier !== undefined) {
|
|
157
|
-
return (`timeTravel: sources ${earlier} and ${i} both record '${id}'. A runtimeStageId is unique ` +
|
|
158
|
-
'within a run, so these are not two legs of one run — a same-executor resume already ' +
|
|
159
|
-
'carries the whole log in ONE snapshot and must not be chained with the paused one.');
|
|
160
|
-
}
|
|
161
|
-
seen.set(id, i);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
let previous;
|
|
165
|
-
for (const [i, span] of spans.entries()) {
|
|
166
|
-
if (span.first === undefined || span.last === undefined)
|
|
167
|
-
continue;
|
|
168
|
-
if (previous && span.first <= previous.last) {
|
|
169
|
-
return (`timeTravel: source ${i} starts at execution index ${span.first}, which is not past ` +
|
|
170
|
-
`source ${previous.idx}'s last (${previous.last}). Chain the sources in run order, and ` +
|
|
171
|
-
'only sources from ONE lineage — the engine never resets the execution counter across a ' +
|
|
172
|
-
'resume, so a fresh run restarting at 0 is a different run, not a continuation.');
|
|
173
|
-
}
|
|
174
|
-
previous = { idx: i, last: span.last };
|
|
175
|
-
}
|
|
176
|
-
for (let k = 1; k < legs.length; k++) {
|
|
177
|
-
const base = legs[k].base;
|
|
178
|
-
if (!base || typeof base !== 'object')
|
|
179
|
-
continue; // no signal on the record — documented degradation
|
|
180
|
-
const before = (0, stateAt_js_1.foldLegs)(legs, k - 1, Number.POSITIVE_INFINITY);
|
|
181
|
-
if (before.basis !== 'initial+log' || before.skipped)
|
|
182
|
-
continue; // not a state a real base can be held to
|
|
183
|
-
if (!sameState(before.state, base, new Set(before.redactedPaths), '')) {
|
|
184
|
-
return (`timeTravel: source ${k}'s initialState is not the state source ${k - 1} folds to. On a resume ` +
|
|
185
|
-
"the later leg's initialState IS the state at the pause, so a leg that begins anywhere else is " +
|
|
186
|
-
'not from one lineage — a different chart, or another run of this one — even when its execution ' +
|
|
187
|
-
'indices happen to be higher.');
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
return undefined;
|
|
191
|
-
}
|
|
192
|
-
exports.refuseChain = refuseChain;
|
|
193
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhaW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3RpbWUtdHJhdmVsL2NoYWluLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBMENHOzs7QUFFSCw0REFBa0Q7QUFDbEQsZ0VBQStEO0FBRS9ELGlEQUFzRDtBQUN0RCw2Q0FBeUQ7QUFhekQsMkVBQTJFO0FBQzNFLFNBQWdCLE1BQU0sQ0FBQyxHQUE0QjtJQUtqRCxJQUFJLEtBQXlCLENBQUM7SUFDOUIsSUFBSSxJQUF3QixDQUFDO0lBQzdCLE1BQU0sR0FBRyxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7SUFDOUIsS0FBSyxNQUFNLE1BQU0sSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUN6QixNQUFNLEVBQUUsR0FBRyxNQUFNLENBQUMsY0FBYyxDQUFDO1FBQ2pDLElBQUksQ0FBQyxFQUFFO1lBQUUsU0FBUztRQUNsQixHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ1osTUFBTSxFQUFFLGNBQWMsRUFBRSxHQUFHLElBQUEsdUNBQW1CLEVBQUMsRUFBRSxDQUFDLENBQUM7UUFDbkQsSUFBSSxNQUFNLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQztZQUFFLFNBQVM7UUFDM0MsSUFBSSxLQUFLLEtBQUssU0FBUyxJQUFJLGNBQWMsR0FBRyxLQUFLO1lBQUUsS0FBSyxHQUFHLGNBQWMsQ0FBQztRQUMxRSxJQUFJLElBQUksS0FBSyxTQUFTLElBQUksY0FBYyxHQUFHLElBQUk7WUFBRSxJQUFJLEdBQUcsY0FBYyxDQUFDO0lBQ3pFLENBQUM7SUFDRCxPQUFPLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQztBQUM5QixDQUFDO0FBbEJELHdCQWtCQztBQUVEOzs7Ozs7Ozs7Ozs7R0FZRztBQUNILFNBQVMsU0FBUyxDQUFDLENBQVUsRUFBRSxD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QUF5QjtnQkFDaEcsZ0dBQWdHO2dCQUNoRyxpR0FBaUc7Z0JBQ2pHLDhCQUE4QixDQUMvQixDQUFDO1FBQ0osQ0FBQztJQUNILENBQUM7SUFDRCxPQUFPLFNBQVMsQ0FBQztBQUNuQixDQUFDO0FBaERELGtDQWdEQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogY2hhaW4udHMg4oCUIHJlYWRpbmcgYSBwYXVzZS9yZXN1bWUgYXMgT05FIGF4aXMuXG4gKlxuICogV0hZIFRISVMgRklMRSBFWElTVFMuIEEgcGF1c2UgYW5kIGl0cyByZXN1bWUgcHJvZHVjZSBUV08gc25hcHNob3RzLiBPbiBhXG4gKiBjcm9zcy1leGVjdXRvciByZXN1bWUgKHRoZSBjaGVja3BvaW50IHdhcyBwZXJzaXN0ZWQgYW5kIGEgZnJlc2ggZXhlY3V0b3JcbiAqIHBpY2tlZCBpdCB1cCkgdGhlIHNlY29uZCBydW4gZ2V0cyBhIGZyZXNoIHJ1bnRpbWU6IGl0cyBgY29tbWl0TG9nYCBzdGFydHMgYXRcbiAqIGluZGV4IDAgYW5kIGhvbGRzIG9ubHkgdGhlIHBvc3QtcmVzdW1lIGNvbW1pdHMsIGFuZCBpdHMgYGluaXRpYWxTdGF0ZWAgaXNcbiAqIHRoZSBzdGF0ZSBhdCB0aGUgcGF1c2UuIFR3byBsb2dzLCB0d28gZGlzam9pbnQgYXhlcyDigJQgc28gYSByZWFkZXIgc2NydWJiaW5nXG4gKiBhIHJlc3VtZWQgcnVuIHNhdyBvbmx5IHRoZSBzZWNvbmQgaGFsZiB1bmxlc3MgdGhlIGFwcGxpY2F0aW9uIGhhZCBrZXB0IHRoZVxuICogcGF1c2VkIHNuYXBzaG90IGFuZCBzdGl0Y2hlZCB0aGUgaGFsdmVzIGl0c2VsZi4gRXZlcnkgYXBwbGljYXRpb24gdGhhdFxuICogcGF1c2VzIHdvdWxkIHdyaXRlIHRoYXQgc3RpdGNoaW5nLCBhbmQgbm9uZSBvZiB0aGVtIG93biB0aGUgYXJpdGhtZXRpYy5cbiAqXG4gKiBUSEUgSE9ORVNUIEJJVCwgdXAgZnJvbnQ6IENPTU1JVCBJTkRJQ0VTIEFSRSBSVU4tTE9DQUwuIFRoZXJlIGlzIG5vIGdsb2JhbFxuICogaW5kZXggYWNyb3NzIGEgY2hhaW4gYW5kIHRoaXMgZmlsZSBkb2VzIG5vdCBpbnZlbnQgb25lIOKAlCBgY29tbWl0SWR4YCBhbmRcbiAqIGBsYXN0Q29tbWl0SWR4YCBrZWVwIGluZGV4aW5nIHRoZWlyIG93biBzb3VyY2UsIGFuZCBldmVyeSBzdG9wIGNhcnJpZXMgdGhlXG4gKiB7QGxpbmsgU3RvcC5zb3VyY2VJZHh9IHRoZXkgYmVsb25nIHRvLiBUaGUgY3Vyc29yJ3MgU1RFUFMgYXJlIHdoYXQgcnVuXG4gKiBhY3Jvc3MgdGhlIHdob2xlIGNoYWluLlxuICpcbiAqIEFORCBUSEUgUkVGVVNBTDogYSBjaGFpbiB0aGF0IGlzIG5vdCBvcmRlcmVkLCBvciB3aG9zZSBsZWdzIGFyZSBub3QgZnJvbSBvbmVcbiAqIGxpbmVhZ2UsIGlzIFJFRlVTRUQgcmF0aGVyIHRoYW4gZ3Vlc3NlZCBhdC4gVGhlIHJlY29yZCBjYXJyaWVzIFRXTyBzaWduYWxzXG4gKiBhbmQgdGhpcyBmaWxlIHJlYWRzIGJvdGg6XG4gKlxuICogLSBUaGUgZXhlY3V0aW9uIGluZGV4IHRoZSBlbmdpbmUgc3RhbXBzIGludG8gZXZlcnkgYHJ1bnRpbWVTdGFnZUlkYCDigJRcbiAqICAgZ2xvYmFsbHkgbW9ub3RvbmljIHBlciBydW4gYW5kLCBkZWxpYmVyYXRlbHksIE5PVCByZXNldCBvbiByZXN1bWUuIFNvIGFcbiAqICAgbGF0ZXIgbGVnJ3MgZmlyc3QgZXhlY3V0aW9uIGluZGV4IG11c3QgYmUgcGFzdCB0aGUgZWFybGllciBsZWcncyBsYXN0LCBhbmRcbiAqICAgbm8gc3RhZ2UgbWF5IGFwcGVhciBpbiB0d28gbGVncy4gVGhpcyBjYXRjaGVzIGEgYmFja3dhcmRzIGNoYWluLCBhIGZyZXNoXG4gKiAgIHJ1biAod2hpY2ggcmVzdGFydHMgYXQgMCkgYW5kIGEgc2FtZS1leGVjdXRvciByZXN1bWUgKHdob3NlIG9uZSBzbmFwc2hvdFxuICogICBhbHJlYWR5IGhvbGRzIGJvdGggaGFsdmVzKS5cbiAqIC0gVGhlIGxhdGVyIGxlZydzIGBpbml0aWFsU3RhdGVgLiBPbiBhIHJlc3VtZSB0aGUgZnJlc2ggcnVudGltZSBpcyBzZWVkZWRcbiAqICAgZnJvbSB0aGUgY2hlY2twb2ludCwgc28gdGhhdCBiYXNlIElTIHRoZSBzdGF0ZSBhdCB0aGUgcGF1c2Ug4oCUIGFuZCB0aGVcbiAqICAgc3RhdGUgdGhlIGVhcmxpZXIgbGVncyBGT0xEIFRPIG11c3QgZGVlcC1lcXVhbCBpdC4gVGhpcyBpcyB3aGF0IGNhdGNoZXMgYVxuICogICBsZWcgZnJvbSBzb21lIE9USEVSIGxpbmVhZ2Ugd2hvc2UgaW5kaWNlcyBtZXJlbHkgaGFwcGVuIHRvIGJlIGhpZ2hlcjogdGhlXG4gKiAgIGNvdW50ZXJzIGxpbmUgdXAgYnkgYWNjaWRlbnQsIHRoZSBzdGF0ZSBuZXZlciBkb2VzLlxuICpcbiAqIEEgY2hhcnQgaWRlbnRpdHkgb3IgYSBsaW5lYWdlIGlkIGlzIE5PVCBvbiB0aGUgcmVjb3JkLCBzbyBub3RoaW5nIGhlcmVcbiAqIHByZXRlbmRzIHRvIGNoZWNrIG9uZS4gQW5kIHdoZXJlIHRoZSBzdGF0ZSBzaWduYWwgaXMgbm90IG9uIHRoZSByZWNvcmRcbiAqIGVpdGhlciDigJQgYSBsZWcgcmVjb3JkZWQgYmVmb3JlIDkuMTcgY2FycmllcyBubyBgaW5pdGlhbFN0YXRlYDsgYW4gZWFybGllclxuICogbGVnIHdpdGggbm8gYmFzZSBmb2xkcyBgJ2xvZy1vbmx5J2A7IGEgbGVnIHdpdGggdW5yZWFkYWJsZSByb3dzIGZvbGRzIGFuXG4gKiBpbmNvbXBsZXRlIHN0YXRlIOKAlCB0aGF0IGNoZWNrIGlzIFNLSVBQRUQsIG5vdCBmYWtlZDogdGhlIGNoYWluIHRoZW4gcmVzdHMgb25cbiAqIHRoZSBpbmRleCBjaGVja3MgYWxvbmUsIGFuZCBldmVyeSBmb2xkJ3MgYGJhc2lzYCBzdGlsbCBzYXlzIHdoYXQgaXQgc3Rvb2RcbiAqIG9uLiBUaGF0IGRlZ3JhZGF0aW9uIGlzIGRvY3VtZW50ZWQgb24gYHJlZnVzZUNoYWluYCwgb24gYHRpbWVUcmF2ZWxgJ3NcbiAqIGBAdGhyb3dzYCwgYW5kIGluIHRoZSBSRUFETUUuXG4gKi9cblxuaW1wb3J0IHsga2luZE9mIH0gZnJvbSAnLi4vY2FwdHVyZS92YWx1ZUtpbmRzLmpzJztcbmltcG9ydCB7IHBhcnNlUnVudGltZVN0YWdlSWQgfSBmcm9tICcuLi9pZHMvcnVudGltZVN0YWdlSWQuanMnO1xuaW1wb3J0IHR5cGUgeyBDb21taXRCdW5kbGUgfSBmcm9tICcuLi9tZW1vcnkvdHlwZXMuanMnO1xuaW1wb3J0IHsgZGVlcEVxdWFsLCBERUxJTSB9IGZyb20gJy4uL21lbW9yeS91dGlscy5qcyc7XG5pbXBvcnQgeyB0eXBlIFJlYWRTb3VyY2UsIGZvbGRMZWdzIH0gZnJvbSAnLi9zdGF0ZUF0LmpzJztcbmltcG9ydCB0eXBlIHsgVGltZVRyYXZlbFNvdXJjZSB9IGZyb20gJy4vdHlwZXMuanMnO1xuXG4vKiogT25lIGxlZyBvZiBhIGNoYWluOiBhIHNvdXJjZSwgaXRzIHJlYWQgbG9nLCBhbmQgd2hlcmUgaXQgc2l0cyBpbiB0aGUgcnVuLiAqL1xuZXhwb3J0IGludGVyZmFjZSBDaGFpbkxlZyB7XG4gIHJlYWRvbmx5IHNvdXJjZTogVGltZVRyYXZlbFNvdXJjZTtcbiAgcmVhZG9ubHkgbG9nOiByZWFkb25seSBDb21taXRCdW5kbGVbXTtcbiAgLyoqIExvd2VzdCBleGVjdXRpb24gaW5kZXggc3RhbXBlZCBpbiB0aGlzIGxlZzsgYHVuZGVmaW5lZGAgZm9yIGFuIGlkLWxlc3MgbG9nLiAqL1xuICByZWFkb25seSBmaXJzdEV4ZWN1dGlvbkluZGV4OiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gIC8qKiBIaWdoZXN0IGV4ZWN1dGlvbiBpbmRleCBzdGFtcGVkIGluIHRoaXMgbGVnLiAqL1xuICByZWFkb25seSBsYXN0RXhlY3V0aW9uSW5kZXg6IG51bWJlciB8IHVuZGVmaW5lZDtcbn1cblxuLyoqIFRoZSBleGVjdXRpb24taW5kZXggc3BhbiBvZiBvbmUgbGVnLCByZWFkIG9mZiBpdHMgYHJ1bnRpbWVTdGFnZUlkYHMuICovXG5leHBvcnQgZnVuY3Rpb24gc3Bhbk9mKGxvZzogcmVhZG9ubHkgQ29tbWl0QnVuZGxlW10pOiB7XG4gIGZpcnN0OiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gIGxhc3Q6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgaWRzOiBTZXQ8c3RyaW5nPjtcbn0ge1xuICBsZXQgZmlyc3Q6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgbGV0IGxhc3Q6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgY29uc3QgaWRzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gIGZvciAoY29uc3QgYnVuZGxlIG9mIGxvZykge1xuICAgIGNvbnN0IGlkID0gYnVuZGxlLnJ1bnRpbWVTdGFnZUlkO1xuICAgIGlmICghaWQpIGNvbnRpbnVlO1xuICAgIGlkcy5hZGQoaWQpO1xuICAgIGNvbnN0IHsgZXhlY3V0aW9uSW5kZXggfSA9IHBhcnNlUnVudGltZVN0YWdlSWQoaWQpO1xuICAgIGlmIChOdW1iZXIuaXNOYU4oZXhlY3V0aW9uSW5kZXgpKSBjb250aW51ZTtcbiAgICBpZiAoZmlyc3QgPT09IHVuZGVmaW5lZCB8fCBleGVjdXRpb25JbmRleCA8IGZpcnN0KSBmaXJzdCA9IGV4ZWN1dGlvbkluZGV4O1xuICAgIGlmIChsYXN0ID09PSB1bmRlZmluZWQgfHwgZXhlY3V0aW9uSW5kZXggPiBsYXN0KSBsYXN0ID0gZXhlY3V0aW9uSW5kZXg7XG4gIH1cbiAgcmV0dXJuIHsgZmlyc3QsIGxhc3QsIGlkcyB9O1xufVxuXG4vKipcbiAqIFN0cnVjdHVyYWwgZXF1YWxpdHkgb2YgdHdvIGZvbGRlZCBzdGF0ZXMsIGlnbm9yaW5nIHRoZSBwYXRocyB0aGUgbG9nIHdhc1xuICogcmVkYWN0ZWQgYXQuXG4gKlxuICogVGhlIGZvbGQgcmVwcm9kdWNlcyBgJ1JFREFDVEVEJ2Agd2hlcmV2ZXIgdGhlIGVuZ2luZSBzY3J1YmJlZCBhIHdyaXRlLCB3aGlsZVxuICogdGhlIGNoZWNrcG9pbnQgdGhhdCBzZWVkZWQgdGhlIHJlc3VtZWQgbGVnIGhvbGRzIHRoZSByZWFsIHZhbHVlIOKAlCBzbyB0aG9zZVxuICogcGF0aHMgQ0FOTk9UIGFncmVlLCBhbmQgYXJlIG5vdCBhc2tlZCB0by4gRXZlcnl0aGluZyBlbHNlIGlzIGRlY2lkZWQgYnkgdGhlXG4gKiBPTkUgZXF1YWxpdHkgbGF3IChgbWVtb3J5L2VxdWFsaXR5LnRzIMK3IGRlZXBFcXVhbGAsIGV2ZXJ5IHZhbHVlIGtpbmQgY29tcGFyZWRcbiAqIGFzIHRoZSByZWNvcmQgaG9sZHMgaXQ7IDkuNDQuMiDigJQgdGhpcyB3YWxrIGhhZCBhIGxhdyBvZiBpdHMgb3duLCB3aGljaCBoZWxkXG4gKiBhbnkgdHdvIFJlZ0V4cHMsIEVycm9ycyBvciBidWZmZXJzIGVxdWFsKS4gQm90aCBzaWRlcyBhcmUgY29waWVzIG9mIG9uZVxuICogcmVjb3JkLCBzbyBhbiBvcGFxdWUgdmFsdWUgY29tcGFyZXMgYXMgYCdjb3BpZXMnYC4gT25seSB0aGUgY29udGFpbmVycyBhYm92ZVxuICogYSByZWRhY3RlZCBwYXRoIGFyZSB3YWxrZWQgaGVyZS5cbiAqL1xuZnVuY3Rpb24gc2FtZVN0YXRlKGE6IHVua25vd24sIGI6IHVua25vd24sIHJlZGFjdGVkOiBSZWFkb25seVNldDxzdHJpbmc+LCBwYXRoOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgaWYgKCFyZWRhY3RlZEJlbG93KHBhdGgsIHJlZGFjdGVkKSkgcmV0dXJuIGRlZXBFcXVhbChhLCBiLCAnY29waWVzJyk7XG4gIGlmIChBcnJheS5pc0FycmF5KGEpICYmIEFycmF5LmlzQXJyYXkoYikpIHtcbiAgICBpZiAoYS5sZW5ndGggIT09IGIubGVuZ3RoKSByZXR1cm4gZmFsc2U7XG4gICAgcmV0dXJuIGEuZXZlcnkoKGl0ZW0sIGkpID0+IHNhbWVTdGF0ZShpdGVtLCBiW2ldLCByZWRhY3RlZCwgcGF0aCA9PT0gJycgPyBTdHJpbmcoaSkgOiBgJHtwYXRofSR7REVMSU19JHtpfWApKTtcbiAgfVxuICBjb25zdCBwbGFpbiA9ICh2OiB1bmtub3duKTogdiBpcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9PlxuICAgIHYgIT09IG51bGwgJiYgdHlwZW9mIHYgPT09ICdvYmplY3QnICYmICFBcnJheS5pc0FycmF5KHYpICYmIGtpbmRPZih2KSA9PT0gJ3BsYWluJztcbiAgaWYgKCFwbGFpbihhKSB8fCAhcGxhaW4oYikpIHJldHVybiBkZWVwRXF1YWwoYSwgYiwgJ2NvcGllcycpO1xuICBjb25zdCBwcmVzZW50ID0gKG86IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSA9PiBPYmplY3Qua2V5cyhvKS5maWx0ZXIoKGspID0+IG9ba10gIT09IHVuZGVmaW5lZCk7XG4gIGNvbnN0IGxlZnRLZXlzID0gcHJlc2VudChhKTtcbiAgY29uc3QgcmlnaHRLZXlzID0gbmV3IFNldChwcmVzZW50KGIpKTtcbiAgaWYgKGxlZnRLZXlzLmxlbmd0aCAhPT0gcmlnaHRLZXlzLnNpemUgfHwgIWxlZnRLZXlzLmV2ZXJ5KChrKSA9PiByaWdodEtleXMuaGFzKGspKSkgcmV0dXJuIGZhbHNlO1xuICByZXR1cm4gbGVmdEtleXMuZXZlcnkoKGspID0+IHtcbiAgICBjb25zdCBjaGlsZFBhdGggPSBwYXRoID09PSAnJyA/IGsgOiBgJHtwYXRofSR7REVMSU19JHtrfWA7XG4gICAgcmV0dXJuIHJlZGFjdGVkLmhhcyhjaGlsZFBhdGgpIHx8IHNhbWVTdGF0ZShhW2tdLCBiW2tdLCByZWRhY3RlZCwgY2hpbGRQYXRoKTtcbiAgfSk7XG59XG5cbi8qKiBJcyBgcGF0aGAsIG9yIGEgcGF0aCBiZWxvdyBpdCwgb25lIHRoZSBsb2cgd2FzIHJlZGFjdGVkIGF0PyAqL1xuZnVuY3Rpb24gcmVkYWN0ZWRCZWxvdyhwYXRoOiBzdHJpbmcsIHJlZGFjdGVkOiBSZWFkb25seVNldDxzdHJpbmc+KTogYm9vbGVhbiB7XG4gIGlmIChyZWRhY3RlZC5zaXplID09PSAwKSByZXR1cm4gZmFsc2U7XG4gIGlmIChwYXRoID09PSAnJykgcmV0dXJuIHRydWU7XG4gIGZvciAoY29uc3QgciBvZiByZWRhY3RlZCkgaWYgKHIgPT09IHBhdGggfHwgci5zdGFydHNXaXRoKGAke3BhdGh9JHtERUxJTX1gKSkgcmV0dXJuIHRydWU7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuLyoqXG4gKiBDaGVjayB0aGF0IGBsZWdzYCByZWFsbHkgYXJlIG9uZSBydW4gcmVhZCBpbiBvcmRlciwgYW5kIHNheSB3aHkgbm90LlxuICpcbiAqIFJldHVybnMgdGhlIHJlZnVzYWwgbWVzc2FnZSwgb3IgYHVuZGVmaW5lZGAgd2hlbiB0aGUgY2hhaW4gaXMgc291bmQuIFRocmVlXG4gKiBkaXN0aW5jdCBmYWlsdXJlcywgYmVjYXVzZSB0aGV5IGFyZSB0aHJlZSBkaWZmZXJlbnQgbWlzdGFrZXMsIGNoZWNrZWQgaW5cbiAqIHRoaXMgb3JkZXI6XG4gKlxuICogLSBSRVBFQVRFRCBTVEFHRSDigJQgb25lIGBydW50aW1lU3RhZ2VJZGAgYXBwZWFycyBpbiB0d28gbGVncy4gSWRzIGFyZSB1bmlxdWVcbiAqICAgd2l0aGluIGEgcnVuLCBzbyBhIHJlcGVhdCBtZWFucyB0aGUgc2FtZSBleGVjdXRpb24gd2FzIHJlY29yZGVkIHR3aWNlOiBhXG4gKiAgIHNhbWUtZXhlY3V0b3IgcmVzdW1lLCB3aG9zZSBzbmFwc2hvdCBBTFJFQURZIGhvbGRzIHRoZSB3aG9sZSBsb2cgYW5kIG5lZWRzXG4gKiAgIG5vIGNoYWluaW5nLCBpcyB0aGUgdXN1YWwgY2F1c2UuXG4gKiAtIE9VVCBPRiBPUkRFUiDigJQgYSBsYXRlciBsZWcncyBmaXJzdCBleGVjdXRpb24gaW5kZXggaXMgbm90IHBhc3QgdGhlIGVhcmxpZXJcbiAqICAgbGVnJ3MgbGFzdC4gRWl0aGVyIHRoZSBzb3VyY2VzIHdlcmUgaGFuZGVkIG92ZXIgYmFja3dhcmRzLCBvciB0aGUgc2Vjb25kXG4gKiAgIGlzIG5vdCBhIGNvbnRpbnVhdGlvbiBhdCBhbGwgKGEgZnJlc2ggcnVuIHJlc3RhcnRzIHRoZSBjb3VudGVyIGF0IDAsIHNvIGFuXG4gKiAgIHVucmVsYXRlZCBzbmFwc2hvdCBmYWlscyBoZXJlIHJhdGhlciB0aGFuIHNpbGVudGx5IGludGVybGVhdmluZykuXG4gKiAtIFdST05HIExJTkVBR0Ug4oCUIGxlZyBrJ3MgYGluaXRpYWxTdGF0ZWAgaXMgbm90IHRoZSBzdGF0ZSBsZWdzIDAuLmstMSBmb2xkXG4gKiAgIHRvLiBPbiBhIHJlc3VtZSB0aGUgbGF0ZXIgbGVnIGlzIHNlZWRlZCBmcm9tIHRoZSBjaGVja3BvaW50LCBzbyBpdHMgYmFzZVxuICogICBJUyB0aGUgc3RhdGUgYXQgdGhlIHBhdXNlOyBhIGxlZyB0aGF0IGJlZ2lucyBhbnl3aGVyZSBlbHNlIGlzIGZyb20gc29tZVxuICogICBvdGhlciBydW4sIGhvd2V2ZXIgaXRzIGluZGljZXMgaGFwcGVuIHRvIGxpbmUgdXAuXG4gKlxuICogVEhFIExJTkVBR0UgQ0hFQ0sgUlVOUyBPTkxZIFdIRVJFIFRIRSBSRUNPUkQgQUxMT1dTIElULCBhbmQgaXMgc2tpcHBlZCDigJRcbiAqIG5ldmVyIGZha2VkIOKAlCBvdGhlcndpc2U6IGxlZyBrIG11c3QgY2FycnkgYW4gYGluaXRpYWxTdGF0ZWAgKGEgcmVjb3JkaW5nXG4gKiBtYWRlIGJlZm9yZSA5LjE3IGhhcyBub25lKSwgYW5kIHRoZSBmb2xkIG9mIHRoZSBsZWdzIGJlZm9yZSBpdCBtdXN0IHN0YW5kIG9uXG4gKiBhIHJlYWwgYmFzZSAoYGJhc2lzOiAnaW5pdGlhbCtsb2cnYCkgd2l0aCBubyB1bnJlYWRhYmxlIHJvd3MgKGBza2lwcGVkYFxuICogYWJzZW50KSDigJQgYSBsb2ctb25seSBvciBnYXBwZWQgZm9sZCBpcyBub3QgYSBzdGF0ZSBhIHJlYWwgYmFzZSBtYXkgYmUgaGVsZFxuICogYWdhaW5zdC4gT24gc3VjaCBhIGNoYWluIHRoZSB0d28gaW5kZXggY2hlY2tzIGFyZSB0aGUgd2hvbGUgZGVmZW5jZSwgYW5kXG4gKiBgZm9sZExlZ3NgJyBsZWcgcnVsZSB0aGVuIENPTlRJTlVFUyB0aGUgZm9sZCBhY3Jvc3MgdGhlIHNlYW0sIHdoaWNoIGlzIHRoZVxuICogcmlnaHQgc3RhdGUgZm9yIGEgcmVhbCByZXN1bWUgYW5kIGlzIHdoYXQgYGJhc2lzYCByZXBvcnRzLiBQYXRocyB0aGUgbG9nXG4gKiB3YXMgcmVkYWN0ZWQgYXQgYXJlIGV4Y2x1ZGVkIGZyb20gdGhlIGNvbXBhcmlzb246IHRoZSBmb2xkIGhvbGRzXG4gKiBgJ1JFREFDVEVEJ2AgdGhlcmUgYW5kIHRoZSBjaGVja3BvaW50IGhvbGRzIHRoZSB2YWx1ZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZnVzZUNoYWluKGxlZ3M6IHJlYWRvbmx5IFJlYWRTb3VyY2VbXSk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGlmIChsZWdzLmxlbmd0aCA9PT0gMCkgcmV0dXJuICd0aW1lVHJhdmVsOiBhIGNoYWluIG5lZWRzIGF0IGxlYXN0IG9uZSBzb3VyY2UsIGdvdCBhbiBlbXB0eSBhcnJheS4nO1xuXG4gIGNvbnN0IHNwYW5zID0gbGVncy5tYXAoKGxlZykgPT4gc3Bhbk9mKGxlZy5sb2cpKTtcbiAgY29uc3Qgc2VlbiA9IG5ldyBNYXA8c3RyaW5nLCBudW1iZXI+KCk7XG4gIGZvciAoY29uc3QgW2ksIHNwYW5dIG9mIHNwYW5zLmVudHJpZXMoKSkge1xuICAgIGZvciAoY29uc3QgaWQgb2Ygc3Bhbi5pZHMpIHtcbiAgICAgIGNvbnN0IGVhcmxpZXIgPSBzZWVuLmdldChpZCk7XG4gICAgICBpZiAoZWFybGllciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgYHRpbWVUcmF2ZWw6IHNvdXJjZXMgJHtlYXJsaWVyfSBhbmQgJHtpfSBib3RoIHJlY29yZCAnJHtpZH0nLiBBIHJ1bnRpbWVTdGFnZUlkIGlzIHVuaXF1ZSBgICtcbiAgICAgICAgICAnd2l0aGluIGEgcnVuLCBzbyB0aGVzZSBhcmUgbm90IHR3byBsZWdzIG9mIG9uZSBydW4g4oCUIGEgc2FtZS1leGVjdXRvciByZXN1bWUgYWxyZWFkeSAnICtcbiAgICAgICAgICAnY2FycmllcyB0aGUgd2hvbGUgbG9nIGluIE9ORSBzbmFwc2hvdCBhbmQgbXVzdCBub3QgYmUgY2hhaW5lZCB3aXRoIHRoZSBwYXVzZWQgb25lLidcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHNlZW4uc2V0KGlkLCBpKTtcbiAgICB9XG4gIH1cblxuICBsZXQgcHJldmlvdXM6IHsgaWR4OiBudW1iZXI7IGxhc3Q6IG51bWJlciB9IHwgdW5kZWZpbmVkO1xuICBmb3IgKGNvbnN0IFtpLCBzcGFuXSBvZiBzcGFucy5lbnRyaWVzKCkpIHtcbiAgICBpZiAoc3Bhbi5maXJzdCA9PT0gdW5kZWZpbmVkIHx8IHNwYW4ubGFzdCA9PT0gdW5kZWZpbmVkKSBjb250aW51ZTtcbiAgICBpZiAocHJldmlvdXMgJiYgc3Bhbi5maXJzdCA8PSBwcmV2aW91cy5sYXN0KSB7XG4gICAgICByZXR1cm4gKFxuICAgICAgICBgdGltZVRyYXZlbDogc291cmNlICR7aX0gc3RhcnRzIGF0IGV4ZWN1dGlvbiBpbmRleCAke3NwYW4uZmlyc3R9LCB3aGljaCBpcyBub3QgcGFzdCBgICtcbiAgICAgICAgYHNvdXJjZSAke3ByZXZpb3VzLmlkeH0ncyBsYXN0ICgke3ByZXZpb3VzLmxhc3R9KS4gQ2hhaW4gdGhlIHNvdXJjZXMgaW4gcnVuIG9yZGVyLCBhbmQgYCArXG4gICAgICAgICdvbmx5IHNvdXJjZXMgZnJvbSBPTkUgbGluZWFnZSDigJQgdGhlIGVuZ2luZSBuZXZlciByZXNldHMgdGhlIGV4ZWN1dGlvbiBjb3VudGVyIGFjcm9zcyBhICcgK1xuICAgICAgICAncmVzdW1lLCBzbyBhIGZyZXNoIHJ1biByZXN0YXJ0aW5nIGF0IDAgaXMgYSBkaWZmZXJlbnQgcnVuLCBub3QgYSBjb250aW51YXRpb24uJ1xuICAgICAgKTtcbiAgICB9XG4gICAgcHJldmlvdXMgPSB7IGlkeDogaSwgbGFzdDogc3Bhbi5sYXN0IH07XG4gIH1cblxuICBmb3IgKGxldCBrID0gMTsgayA8IGxlZ3MubGVuZ3RoOyBrKyspIHtcbiAgICBjb25zdCBiYXNlID0gbGVnc1trXS5iYXNlO1xuICAgIGlmICghYmFzZSB8fCB0eXBlb2YgYmFzZSAhPT0gJ29iamVjdCcpIGNvbnRpbnVlOyAvLyBubyBzaWduYWwgb24gdGhlIHJlY29yZCDigJQgZG9jdW1lbnRlZCBkZWdyYWRhdGlvblxuICAgIGNvbnN0IGJlZm9yZSA9IGZvbGRMZWdzKGxlZ3MsIGsgLSAxLCBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFkpO1xuICAgIGlmIChiZWZvcmUuYmFzaXMgIT09ICdpbml0aWFsK2xvZycgfHwgYmVmb3JlLnNraXBwZWQpIGNvbnRpbnVlOyAvLyBub3QgYSBzdGF0ZSBhIHJlYWwgYmFzZSBjYW4gYmUgaGVsZCB0b1xuICAgIGlmICghc2FtZVN0YXRlKGJlZm9yZS5zdGF0ZSwgYmFzZSwgbmV3IFNldChiZWZvcmUucmVkYWN0ZWRQYXRocyksICcnKSkge1xuICAgICAgcmV0dXJuIChcbiAgICAgICAgYHRpbWVUcmF2ZWw6IHNvdXJjZSAke2t9J3MgaW5pdGlhbFN0YXRlIGlzIG5vdCB0aGUgc3RhdGUgc291cmNlICR7ayAtIDF9IGZvbGRzIHRvLiBPbiBhIHJlc3VtZSBgICtcbiAgICAgICAgXCJ0aGUgbGF0ZXIgbGVnJ3MgaW5pdGlhbFN0YXRlIElTIHRoZSBzdGF0ZSBhdCB0aGUgcGF1c2UsIHNvIGEgbGVnIHRoYXQgYmVnaW5zIGFueXdoZXJlIGVsc2UgaXMgXCIgK1xuICAgICAgICAnbm90IGZyb20gb25lIGxpbmVhZ2Ug4oCUIGEgZGlmZmVyZW50IGNoYXJ0LCBvciBhbm90aGVyIHJ1biBvZiB0aGlzIG9uZSDigJQgZXZlbiB3aGVuIGl0cyBleGVjdXRpb24gJyArXG4gICAgICAgICdpbmRpY2VzIGhhcHBlbiB0byBiZSBoaWdoZXIuJ1xuICAgICAgKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cbiJdfQ==
|