footprintjs 4.16.0 → 4.17.2
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 +567 -82
- package/CLAUDE.md +57 -0
- package/README.md +2 -0
- package/dist/advanced.js +4 -2
- package/dist/detach.js +78 -0
- package/dist/esm/advanced.js +2 -1
- package/dist/esm/detach.js +57 -0
- package/dist/esm/lib/builder/FlowChartBuilder.js +171 -61
- package/dist/esm/lib/contract/openapi.js +4 -5
- package/dist/esm/lib/contract/schema.js +115 -4
- package/dist/esm/lib/decide/decide.js +4 -5
- package/dist/esm/lib/decide/evidence.js +3 -2
- package/dist/esm/lib/detach/drivers/immediate.js +66 -0
- package/dist/esm/lib/detach/drivers/microtaskBatch.js +113 -0
- package/dist/esm/lib/detach/drivers/sendBeacon.js +78 -0
- package/dist/esm/lib/detach/drivers/setImmediate.js +81 -0
- package/dist/esm/lib/detach/drivers/setTimeout.js +69 -0
- package/dist/esm/lib/detach/drivers/workerThread.js +117 -0
- package/dist/esm/lib/detach/flush.js +91 -0
- package/dist/esm/lib/detach/handle.js +134 -0
- package/dist/esm/lib/detach/registry.js +97 -0
- package/dist/esm/lib/detach/runChild.js +40 -0
- package/dist/esm/lib/detach/spawn.js +86 -0
- package/dist/esm/lib/detach/types.js +37 -0
- package/dist/esm/lib/engine/errors/errorInfo.js +4 -4
- package/dist/esm/lib/engine/graph/StageNode.js +2 -2
- package/dist/esm/lib/engine/handlers/ChildrenExecutor.js +9 -8
- package/dist/esm/lib/engine/handlers/ContinuationResolver.js +12 -9
- package/dist/esm/lib/engine/handlers/DeciderHandler.js +7 -8
- package/dist/esm/lib/engine/handlers/ExtractorRunner.js +14 -8
- package/dist/esm/lib/engine/handlers/NodeResolver.js +5 -3
- package/dist/esm/lib/engine/handlers/RuntimeStructureManager.js +11 -14
- package/dist/esm/lib/engine/handlers/SelectorHandler.js +9 -9
- package/dist/esm/lib/engine/handlers/StageRunner.js +9 -11
- package/dist/esm/lib/engine/handlers/SubflowExecutor.js +13 -12
- package/dist/esm/lib/engine/handlers/SubflowInputMapper.js +4 -4
- package/dist/esm/lib/engine/narrative/CombinedNarrativeRecorder.js +85 -96
- package/dist/esm/lib/engine/narrative/FlowRecorderDispatcher.js +18 -36
- package/dist/esm/lib/engine/narrative/NarrativeFlowRecorder.js +6 -5
- package/dist/esm/lib/engine/narrative/recorders/AdaptiveNarrativeFlowRecorder.js +7 -6
- package/dist/esm/lib/engine/narrative/recorders/ManifestFlowRecorder.js +10 -10
- package/dist/esm/lib/engine/narrative/recorders/MilestoneNarrativeFlowRecorder.js +5 -3
- package/dist/esm/lib/engine/narrative/recorders/ProgressiveNarrativeFlowRecorder.js +4 -3
- package/dist/esm/lib/engine/narrative/recorders/RLENarrativeFlowRecorder.js +4 -4
- package/dist/esm/lib/engine/narrative/recorders/SeparateNarrativeFlowRecorder.js +5 -6
- package/dist/esm/lib/engine/narrative/recorders/SilentNarrativeFlowRecorder.js +5 -6
- package/dist/esm/lib/engine/narrative/recorders/WindowedNarrativeFlowRecorder.js +5 -3
- package/dist/esm/lib/engine/traversal/FlowchartTraverser.js +97 -71
- package/dist/esm/lib/memory/DiagnosticCollector.js +6 -8
- package/dist/esm/lib/memory/EventLog.js +5 -3
- package/dist/esm/lib/memory/SharedMemory.js +3 -2
- package/dist/esm/lib/memory/StageContext.js +44 -14
- package/dist/esm/lib/memory/TransactionBuffer.js +9 -8
- package/dist/esm/lib/memory/backtrack.js +3 -4
- package/dist/esm/lib/memory/commitLogUtils.js +2 -2
- package/dist/esm/lib/memory/utils.js +2 -3
- package/dist/esm/lib/pause/types.js +33 -14
- package/dist/esm/lib/reactive/createTypedScope.js +10 -8
- package/dist/esm/lib/reactive/types.js +3 -1
- package/dist/esm/lib/recorder/BoundaryStateTracker.js +263 -0
- package/dist/esm/lib/recorder/CompositeRecorder.js +3 -1
- package/dist/esm/lib/recorder/InOutRecorder.js +5 -6
- package/dist/esm/lib/recorder/KeyedRecorder.js +2 -4
- package/dist/esm/lib/recorder/QualityRecorder.js +15 -14
- package/dist/esm/lib/recorder/SequenceRecorder.js +11 -12
- package/dist/esm/lib/recorder/TopologyRecorder.js +36 -40
- package/dist/esm/lib/recorder/index.js +2 -1
- package/dist/esm/lib/recorder/qualityTrace.js +4 -5
- package/dist/esm/lib/runner/ExecutionRuntime.js +20 -4
- package/dist/esm/lib/runner/FlowChartExecutor.js +99 -55
- package/dist/esm/lib/runner/RunContext.js +5 -3
- package/dist/esm/lib/runner/RunnableChart.js +7 -9
- package/dist/esm/lib/runner/getSubtreeSnapshot.js +4 -5
- package/dist/esm/lib/schema/errors.js +4 -3
- package/dist/esm/lib/schema/validate.js +4 -5
- package/dist/esm/lib/scope/ScopeFacade.js +52 -35
- package/dist/esm/lib/scope/providers/baseStateCompatible.js +9 -9
- package/dist/esm/lib/scope/providers/guards.js +2 -2
- package/dist/esm/lib/scope/recorders/DebugRecorder.js +9 -7
- package/dist/esm/lib/scope/recorders/MetricRecorder.js +10 -8
- package/dist/esm/lib/scope/state/zod/defineScopeFromZod.js +2 -3
- package/dist/esm/lib/scope/state/zod/resolver.js +2 -3
- package/dist/esm/lib/scope/state/zod/scopeFactory.js +16 -20
- package/dist/esm/lib/scope/state/zod/utils/validateHelper.js +57 -14
- package/dist/esm/trace.js +4 -1
- package/dist/lib/builder/FlowChartBuilder.js +171 -61
- package/dist/lib/contract/openapi.js +4 -5
- package/dist/lib/contract/schema.js +115 -4
- package/dist/lib/decide/decide.js +4 -5
- package/dist/lib/decide/evidence.js +3 -2
- package/dist/lib/detach/drivers/immediate.js +70 -0
- package/dist/lib/detach/drivers/microtaskBatch.js +117 -0
- package/dist/lib/detach/drivers/sendBeacon.js +82 -0
- package/dist/lib/detach/drivers/setImmediate.js +85 -0
- package/dist/lib/detach/drivers/setTimeout.js +73 -0
- package/dist/lib/detach/drivers/workerThread.js +121 -0
- package/dist/lib/detach/flush.js +95 -0
- package/dist/lib/detach/handle.js +140 -0
- package/dist/lib/detach/registry.js +106 -0
- package/dist/lib/detach/runChild.js +67 -0
- package/dist/lib/detach/spawn.js +92 -0
- package/dist/lib/detach/types.js +38 -0
- package/dist/lib/engine/errors/errorInfo.js +4 -4
- package/dist/lib/engine/graph/StageNode.js +2 -2
- package/dist/lib/engine/handlers/ChildrenExecutor.js +9 -8
- package/dist/lib/engine/handlers/ContinuationResolver.js +12 -9
- package/dist/lib/engine/handlers/DeciderHandler.js +7 -8
- package/dist/lib/engine/handlers/ExtractorRunner.js +14 -8
- package/dist/lib/engine/handlers/NodeResolver.js +5 -3
- package/dist/lib/engine/handlers/RuntimeStructureManager.js +11 -14
- package/dist/lib/engine/handlers/SelectorHandler.js +9 -9
- package/dist/lib/engine/handlers/StageRunner.js +9 -11
- package/dist/lib/engine/handlers/SubflowExecutor.js +13 -12
- package/dist/lib/engine/handlers/SubflowInputMapper.js +4 -4
- package/dist/lib/engine/narrative/CombinedNarrativeRecorder.js +85 -96
- package/dist/lib/engine/narrative/FlowRecorderDispatcher.js +18 -36
- package/dist/lib/engine/narrative/NarrativeFlowRecorder.js +6 -5
- package/dist/lib/engine/narrative/recorders/AdaptiveNarrativeFlowRecorder.js +7 -6
- package/dist/lib/engine/narrative/recorders/ManifestFlowRecorder.js +10 -10
- package/dist/lib/engine/narrative/recorders/MilestoneNarrativeFlowRecorder.js +5 -3
- package/dist/lib/engine/narrative/recorders/ProgressiveNarrativeFlowRecorder.js +4 -3
- package/dist/lib/engine/narrative/recorders/RLENarrativeFlowRecorder.js +4 -4
- package/dist/lib/engine/narrative/recorders/SeparateNarrativeFlowRecorder.js +5 -6
- package/dist/lib/engine/narrative/recorders/SilentNarrativeFlowRecorder.js +5 -6
- package/dist/lib/engine/narrative/recorders/WindowedNarrativeFlowRecorder.js +5 -3
- package/dist/lib/engine/traversal/FlowchartTraverser.js +97 -71
- package/dist/lib/memory/DiagnosticCollector.js +6 -8
- package/dist/lib/memory/EventLog.js +5 -3
- package/dist/lib/memory/SharedMemory.js +3 -2
- package/dist/lib/memory/StageContext.js +44 -14
- package/dist/lib/memory/TransactionBuffer.js +9 -8
- package/dist/lib/memory/backtrack.js +3 -4
- package/dist/lib/memory/commitLogUtils.js +2 -2
- package/dist/lib/memory/utils.js +2 -3
- package/dist/lib/pause/types.js +33 -14
- package/dist/lib/reactive/createTypedScope.js +10 -8
- package/dist/lib/reactive/types.js +3 -1
- package/dist/lib/recorder/BoundaryStateTracker.js +267 -0
- package/dist/lib/recorder/CompositeRecorder.js +3 -1
- package/dist/lib/recorder/InOutRecorder.js +5 -6
- package/dist/lib/recorder/KeyedRecorder.js +2 -4
- package/dist/lib/recorder/QualityRecorder.js +15 -14
- package/dist/lib/recorder/SequenceRecorder.js +11 -12
- package/dist/lib/recorder/TopologyRecorder.js +36 -40
- package/dist/lib/recorder/index.js +4 -2
- package/dist/lib/recorder/qualityTrace.js +4 -5
- package/dist/lib/runner/ExecutionRuntime.js +20 -4
- package/dist/lib/runner/FlowChartExecutor.js +99 -55
- package/dist/lib/runner/RunContext.js +5 -3
- package/dist/lib/runner/RunnableChart.js +7 -9
- package/dist/lib/runner/getSubtreeSnapshot.js +4 -5
- package/dist/lib/schema/errors.js +4 -3
- package/dist/lib/schema/validate.js +4 -5
- package/dist/lib/scope/ScopeFacade.js +52 -35
- package/dist/lib/scope/providers/baseStateCompatible.js +9 -9
- package/dist/lib/scope/providers/guards.js +2 -2
- package/dist/lib/scope/recorders/DebugRecorder.js +9 -7
- package/dist/lib/scope/recorders/MetricRecorder.js +10 -8
- package/dist/lib/scope/state/zod/defineScopeFromZod.js +2 -3
- package/dist/lib/scope/state/zod/resolver.js +2 -3
- package/dist/lib/scope/state/zod/scopeFactory.js +16 -20
- package/dist/lib/scope/state/zod/utils/validateHelper.js +57 -14
- package/dist/trace.js +6 -2
- package/dist/types/advanced.d.ts +1 -0
- package/dist/types/detach.d.ts +59 -0
- package/dist/types/lib/builder/FlowChartBuilder.d.ts +81 -0
- package/dist/types/lib/detach/drivers/immediate.d.ts +39 -0
- package/dist/types/lib/detach/drivers/microtaskBatch.d.ts +57 -0
- package/dist/types/lib/detach/drivers/sendBeacon.d.ts +38 -0
- package/dist/types/lib/detach/drivers/setImmediate.d.ts +32 -0
- package/dist/types/lib/detach/drivers/setTimeout.d.ts +34 -0
- package/dist/types/lib/detach/drivers/workerThread.d.ts +50 -0
- package/dist/types/lib/detach/flush.d.ts +62 -0
- package/dist/types/lib/detach/handle.d.ts +83 -0
- package/dist/types/lib/detach/registry.d.ts +82 -0
- package/dist/types/lib/detach/runChild.d.ts +41 -0
- package/dist/types/lib/detach/spawn.d.ts +64 -0
- package/dist/types/lib/detach/types.d.ts +200 -0
- package/dist/types/lib/engine/traversal/FlowchartTraverser.d.ts +0 -1
- package/dist/types/lib/engine/types.d.ts +0 -1
- package/dist/types/lib/reactive/types.d.ts +4 -0
- package/dist/types/lib/recorder/BoundaryStateTracker.d.ts +215 -0
- package/dist/types/lib/recorder/index.d.ts +1 -0
- package/dist/types/lib/runner/FlowChartExecutor.d.ts +28 -0
- package/dist/types/lib/scope/ScopeFacade.d.ts +4 -0
- package/dist/types/lib/scope/state/zod/utils/validateHelper.d.ts +13 -1
- package/dist/types/trace.d.ts +1 -0
- package/package.json +6 -1
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* detach/drivers/microtaskBatch.ts — Batch detached work into ONE microtask.
|
|
4
|
+
*
|
|
5
|
+
* Pattern: Producer-consumer with batched flush. Same shape as
|
|
6
|
+
* agentfootprint's `EventDispatcher` flush queue and the React
|
|
7
|
+
* reconciler's microtask scheduling — accumulate during the
|
|
8
|
+
* current sync slice, drain at the next microtask boundary.
|
|
9
|
+
* Role: Default driver for in-process detach. Cheapest scheduling
|
|
10
|
+
* primitive on V8/JSC: one `queueMicrotask` per batch
|
|
11
|
+
* regardless of how many work items, so the perf budget
|
|
12
|
+
* amortizes. Suitable for browser AND node AND edge runtimes
|
|
13
|
+
* (queueMicrotask is universal since 2018).
|
|
14
|
+
*
|
|
15
|
+
* Lifecycle:
|
|
16
|
+
*
|
|
17
|
+
* schedule(child, input, refId) ← driver entry
|
|
18
|
+
* └─ create handle (queued)
|
|
19
|
+
* └─ register in detachRegistry
|
|
20
|
+
* └─ push work item onto local queue
|
|
21
|
+
* └─ if no microtask scheduled yet → queueMicrotask(flush)
|
|
22
|
+
* └─ return handle (sync — passive recorder rule)
|
|
23
|
+
*
|
|
24
|
+
* flush() (microtask) ← deferred
|
|
25
|
+
* └─ swap out queue (drain races safely)
|
|
26
|
+
* └─ for each item: _markRunning, await runChild, _markDone/_markFailed
|
|
27
|
+
* └─ unregister handle from detachRegistry
|
|
28
|
+
*
|
|
29
|
+
* Why microtask (and not setImmediate / setTimeout):
|
|
30
|
+
* - Microtasks run BEFORE returning to the event loop — guarantees
|
|
31
|
+
* the work finishes within the current "tick" if the runtime allows
|
|
32
|
+
* - Lowest possible deferral cost (~50ns on modern V8)
|
|
33
|
+
* - Works in EVERY JS runtime (browser, node, deno, bun, edge)
|
|
34
|
+
* - Doesn't require any timer infrastructure → no GC pressure
|
|
35
|
+
*
|
|
36
|
+
* Re-entrancy:
|
|
37
|
+
* - If `runChild` calls `schedule()` for nested detach, the new item
|
|
38
|
+
* lands on the SAME queue. Because `scheduled` flips back to false
|
|
39
|
+
* at the start of `flush`, the new item triggers a fresh microtask.
|
|
40
|
+
* - Worst-case: O(n) microtasks for n nested levels. Acceptable —
|
|
41
|
+
* real-world detach trees are shallow.
|
|
42
|
+
*/
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.microtaskBatchDriver = exports.createMicrotaskBatchDriver = void 0;
|
|
45
|
+
const handle_js_1 = require("../handle.js");
|
|
46
|
+
const registry_js_1 = require("../registry.js");
|
|
47
|
+
const runChild_js_1 = require("../runChild.js");
|
|
48
|
+
/**
|
|
49
|
+
* Build a microtask-batch driver wired to a custom child runner. Most
|
|
50
|
+
* consumers want the default singleton `microtaskBatchDriver` instead;
|
|
51
|
+
* this factory exists for tests and for advanced consumers who want to
|
|
52
|
+
* inject their own runner (e.g., a runner that wraps the child in a
|
|
53
|
+
* tracing context).
|
|
54
|
+
*/
|
|
55
|
+
function createMicrotaskBatchDriver(runChild = runChild_js_1.defaultRunChild) {
|
|
56
|
+
// Per-driver-instance queue and flush guard. Closed over by `schedule`
|
|
57
|
+
// and `flush` so each call to `createMicrotaskBatchDriver` gets its
|
|
58
|
+
// own isolated batch (test isolation, multi-tenant scenarios).
|
|
59
|
+
const queue = [];
|
|
60
|
+
let scheduled = false;
|
|
61
|
+
function flush() {
|
|
62
|
+
// Reset BEFORE draining so re-entrant schedule()s during runChild
|
|
63
|
+
// queue a fresh microtask instead of joining the in-flight drain.
|
|
64
|
+
scheduled = false;
|
|
65
|
+
const items = queue.splice(0);
|
|
66
|
+
for (const item of items) {
|
|
67
|
+
// Each item runs concurrently — no awaits here, so the outer
|
|
68
|
+
// for-loop completes within this microtask. Errors inside
|
|
69
|
+
// `executeOne` are routed to the handle, not thrown. The promise
|
|
70
|
+
// is intentionally not awaited; ignore-promise-returned via the
|
|
71
|
+
// explicit no-op .then() pattern that the project's lint config
|
|
72
|
+
// accepts (vs `void`, which `no-void` rejects).
|
|
73
|
+
executeOne(item, runChild).then(undefined, undefined);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
name: 'microtask-batch',
|
|
78
|
+
capabilities: { browserSafe: true, nodeSafe: true, edgeSafe: true },
|
|
79
|
+
schedule(child, input, refId) {
|
|
80
|
+
const handle = (0, handle_js_1.createHandle)(refId);
|
|
81
|
+
(0, registry_js_1.register)(handle);
|
|
82
|
+
queue.push({ child, input, handle });
|
|
83
|
+
if (!scheduled) {
|
|
84
|
+
scheduled = true;
|
|
85
|
+
queueMicrotask(flush);
|
|
86
|
+
}
|
|
87
|
+
return handle;
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
exports.createMicrotaskBatchDriver = createMicrotaskBatchDriver;
|
|
92
|
+
/**
|
|
93
|
+
* Per-item execution. Marks the handle running, awaits the runner,
|
|
94
|
+
* routes outcome to the handle, cleans up the registry entry. Never
|
|
95
|
+
* throws — errors land on the handle (passive recorder rule).
|
|
96
|
+
*/
|
|
97
|
+
async function executeOne(item, runChild) {
|
|
98
|
+
const impl = (0, handle_js_1.asImpl)(item.handle);
|
|
99
|
+
impl._markRunning();
|
|
100
|
+
try {
|
|
101
|
+
const result = await runChild(item.child, item.input);
|
|
102
|
+
impl._markDone(result);
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
impl._markFailed(err instanceof Error ? err : new Error(String(err)));
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
(0, registry_js_1.unregister)(impl.id);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Default singleton. Most consumers import this and pass it to
|
|
113
|
+
* `executor.detachAndJoinLater(child, input, { driver: microtaskBatchDriver })`
|
|
114
|
+
* (or rely on it being the executor's default driver, set in T5b).
|
|
115
|
+
*/
|
|
116
|
+
exports.microtaskBatchDriver = createMicrotaskBatchDriver();
|
|
117
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWljcm90YXNrQmF0Y2guanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL2RldGFjaC9kcml2ZXJzL21pY3JvdGFza0JhdGNoLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXdDRzs7O0FBR0gsNENBQW9EO0FBQ3BELGdEQUFzRDtBQUN0RCxnREFBbUU7QUFTbkU7Ozs7OztHQU1HO0FBQ0gsU0FBZ0IsMEJBQTBCLENBQUMsV0FBd0IsNkJBQWU7SUFDaEYsdUVBQXVFO0lBQ3ZFLG9FQUFvRTtJQUNwRSwrREFBK0Q7SUFDL0QsTUFBTSxLQUFLLEdBQWUsRUFBRSxDQUFDO0lBQzdCLElBQUksU0FBUyxHQUFHLEtBQUssQ0FBQztJQUV0QixTQUFTLEtBQUs7UUFDWixrRUFBa0U7UUFDbEUsa0VBQWtFO1FBQ2xFLFNBQVMsR0FBRyxLQUFLLENBQUM7UUFDbEIsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM5QixLQUFLLE1BQU0sSUFBSSxJQUFJLEtBQUssRUFBRSxDQUFDO1lBQ3pCLDZEQUE2RDtZQUM3RCwwREFBMEQ7WUFDMUQsaUVBQWlFO1lBQ2pFLGdFQUFnRTtZQUNoRSxnRUFBZ0U7WUFDaEUsZ0RBQWdEO1lBQ2hELFVBQVUsQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FBQztRQUN4RCxDQUFDO0lBQ0gsQ0FBQztJQUVELE9BQU87UUFDTCxJQUFJLEVBQUUsaUJBQWlCO1FBQ3ZCLFlBQVksRUFBRSxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFO1FBQ25FLFFBQVEsQ0FBQyxLQUFnQixFQUFFLEtBQWMsRUFBRSxLQUFhO1lBQ3RELE1BQU0sTUFBTSxHQUFHLElBQUEsd0JBQVksRUFBQyxLQUFLLENBQUMsQ0FBQztZQUNuQyxJQUFBLHNCQUFRLEVBQUMsTUFBTSxDQUFDLENBQUM7WUFDakIsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztZQUNyQyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7Z0JBQ2YsU0FBUyxHQUFHLElBQUksQ0FBQztnQkFDakIsY0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3hCLENBQUM7WUFDRCxPQUFPLE1BQU0sQ0FBQztRQUNoQixDQUFDO0tBQ0YsQ0FBQztBQUNKLENBQUM7QUFyQ0QsZ0VBcUNDO0FBRUQ7Ozs7R0FJRztBQUNILEtBQUssVUFBVSxVQUFVLENBQUMsSUFBYyxFQUFFLFFBQXFCO0lBQzdELE1BQU0sSUFBSSxHQUFHLElBQUEsa0JBQU0sRUFBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDakMsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQ3BCLElBQUksQ0FBQztRQUNILE1BQU0sTUFBTSxHQUFHLE1BQU0sUUFBUSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3RELElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDekIsQ0FBQztJQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7UUFDYixJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN4RSxDQUFDO1lBQVMsQ0FBQztRQUNULElBQUEsd0JBQVUsRUFBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDdEIsQ0FBQztBQUNILENBQUM7QUFFRDs7OztHQUlHO0FBQ1UsUUFBQSxvQkFBb0IsR0FBaUIsMEJBQTBCLEVBQUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogZGV0YWNoL2RyaXZlcnMvbWljcm90YXNrQmF0Y2gudHMg4oCUIEJhdGNoIGRldGFjaGVkIHdvcmsgaW50byBPTkUgbWljcm90YXNrLlxuICpcbiAqIFBhdHRlcm46ICBQcm9kdWNlci1jb25zdW1lciB3aXRoIGJhdGNoZWQgZmx1c2guIFNhbWUgc2hhcGUgYXNcbiAqICAgICAgICAgICBhZ2VudGZvb3RwcmludCdzIGBFdmVudERpc3BhdGNoZXJgIGZsdXNoIHF1ZXVlIGFuZCB0aGUgUmVhY3RcbiAqICAgICAgICAgICByZWNvbmNpbGVyJ3MgbWljcm90YXNrIHNjaGVkdWxpbmcg4oCUIGFjY3VtdWxhdGUgZHVyaW5nIHRoZVxuICogICAgICAgICAgIGN1cnJlbnQgc3luYyBzbGljZSwgZHJhaW4gYXQgdGhlIG5leHQgbWljcm90YXNrIGJvdW5kYXJ5LlxuICogUm9sZTogICAgIERlZmF1bHQgZHJpdmVyIGZvciBpbi1wcm9jZXNzIGRldGFjaC4gQ2hlYXBlc3Qgc2NoZWR1bGluZ1xuICogICAgICAgICAgIHByaW1pdGl2ZSBvbiBWOC9KU0M6IG9uZSBgcXVldWVNaWNyb3Rhc2tgIHBlciBiYXRjaFxuICogICAgICAgICAgIHJlZ2FyZGxlc3Mgb2YgaG93IG1hbnkgd29yayBpdGVtcywgc28gdGhlIHBlcmYgYnVkZ2V0XG4gKiAgICAgICAgICAgYW1vcnRpemVzLiBTdWl0YWJsZSBmb3IgYnJvd3NlciBBTkQgbm9kZSBBTkQgZWRnZSBydW50aW1lc1xuICogICAgICAgICAgIChxdWV1ZU1pY3JvdGFzayBpcyB1bml2ZXJzYWwgc2luY2UgMjAxOCkuXG4gKlxuICogTGlmZWN5Y2xlOlxuICpcbiAqICAgc2NoZWR1bGUoY2hpbGQsIGlucHV0LCByZWZJZCkgICAgICAgICAgICDihpAgZHJpdmVyIGVudHJ5XG4gKiAgICAg4pSU4pSAIGNyZWF0ZSBoYW5kbGUgKHF1ZXVlZClcbiAqICAgICDilJTilIAgcmVnaXN0ZXIgaW4gZGV0YWNoUmVnaXN0cnlcbiAqICAgICDilJTilIAgcHVzaCB3b3JrIGl0ZW0gb250byBsb2NhbCBxdWV1ZVxuICogICAgIOKUlOKUgCBpZiBubyBtaWNyb3Rhc2sgc2NoZWR1bGVkIHlldCDihpIgcXVldWVNaWNyb3Rhc2soZmx1c2gpXG4gKiAgICAg4pSU4pSAIHJldHVybiBoYW5kbGUgKHN5bmMg4oCUIHBhc3NpdmUgcmVjb3JkZXIgcnVsZSlcbiAqXG4gKiAgIGZsdXNoKCkgKG1pY3JvdGFzaykgICAgICAgICAgICAgICAgICAgICAgIOKGkCBkZWZlcnJlZFxuICogICAgIOKUlOKUgCBzd2FwIG91dCBxdWV1ZSAoZHJhaW4gcmFjZXMgc2FmZWx5KVxuICogICAgIOKUlOKUgCBmb3IgZWFjaCBpdGVtOiBfbWFya1J1bm5pbmcsIGF3YWl0IHJ1bkNoaWxkLCBfbWFya0RvbmUvX21hcmtGYWlsZWRcbiAqICAgICDilJTilIAgdW5yZWdpc3RlciBoYW5kbGUgZnJvbSBkZXRhY2hSZWdpc3RyeVxuICpcbiAqIFdoeSBtaWNyb3Rhc2sgKGFuZCBub3Qgc2V0SW1tZWRpYXRlIC8gc2V0VGltZW91dCk6XG4gKiAgIC0gTWljcm90YXNrcyBydW4gQkVGT1JFIHJldHVybmluZyB0byB0aGUgZXZlbnQgbG9vcCDigJQgZ3VhcmFudGVlc1xuICogICAgIHRoZSB3b3JrIGZpbmlzaGVzIHdpdGhpbiB0aGUgY3VycmVudCBcInRpY2tcIiBpZiB0aGUgcnVudGltZSBhbGxvd3NcbiAqICAgLSBMb3dlc3QgcG9zc2libGUgZGVmZXJyYWwgY29zdCAofjUwbnMgb24gbW9kZXJuIFY4KVxuICogICAtIFdvcmtzIGluIEVWRVJZIEpTIHJ1bnRpbWUgKGJyb3dzZXIsIG5vZGUsIGRlbm8sIGJ1biwgZWRnZSlcbiAqICAgLSBEb2Vzbid0IHJlcXVpcmUgYW55IHRpbWVyIGluZnJhc3RydWN0dXJlIOKGkiBubyBHQyBwcmVzc3VyZVxuICpcbiAqIFJlLWVudHJhbmN5OlxuICogICAtIElmIGBydW5DaGlsZGAgY2FsbHMgYHNjaGVkdWxlKClgIGZvciBuZXN0ZWQgZGV0YWNoLCB0aGUgbmV3IGl0ZW1cbiAqICAgICBsYW5kcyBvbiB0aGUgU0FNRSBxdWV1ZS4gQmVjYXVzZSBgc2NoZWR1bGVkYCBmbGlwcyBiYWNrIHRvIGZhbHNlXG4gKiAgICAgYXQgdGhlIHN0YXJ0IG9mIGBmbHVzaGAsIHRoZSBuZXcgaXRlbSB0cmlnZ2VycyBhIGZyZXNoIG1pY3JvdGFzay5cbiAqICAgLSBXb3JzdC1jYXNlOiBPKG4pIG1pY3JvdGFza3MgZm9yIG4gbmVzdGVkIGxldmVscy4gQWNjZXB0YWJsZSDigJRcbiAqICAgICByZWFsLXdvcmxkIGRldGFjaCB0cmVlcyBhcmUgc2hhbGxvdy5cbiAqL1xuXG5pbXBvcnQgdHlwZSB7IEZsb3dDaGFydCB9IGZyb20gJy4uLy4uL2J1aWxkZXIvdHlwZXMuanMnO1xuaW1wb3J0IHsgYXNJbXBsLCBjcmVhdGVIYW5kbGUgfSBmcm9tICcuLi9oYW5kbGUuanMnO1xuaW1wb3J0IHsgcmVnaXN0ZXIsIHVucmVnaXN0ZXIgfSBmcm9tICcuLi9yZWdpc3RyeS5qcyc7XG5pbXBvcnQgeyB0eXBlIENoaWxkUnVubmVyLCBkZWZhdWx0UnVuQ2hpbGQgfSBmcm9tICcuLi9ydW5DaGlsZC5qcyc7XG5pbXBvcnQgdHlwZSB7IERldGFjaERyaXZlciwgRGV0YWNoSGFuZGxlIH0gZnJvbSAnLi4vdHlwZXMuanMnO1xuXG5pbnRlcmZhY2UgV29ya0l0ZW0ge1xuICByZWFkb25seSBjaGlsZDogRmxvd0NoYXJ0O1xuICByZWFkb25seSBpbnB1dDogdW5rbm93bjtcbiAgcmVhZG9ubHkgaGFuZGxlOiBEZXRhY2hIYW5kbGU7XG59XG5cbi8qKlxuICogQnVpbGQgYSBtaWNyb3Rhc2stYmF0Y2ggZHJpdmVyIHdpcmVkIHRvIGEgY3VzdG9tIGNoaWxkIHJ1bm5lci4gTW9zdFxuICogY29uc3VtZXJzIHdhbnQgdGhlIGRlZmF1bHQgc2luZ2xldG9uIGBtaWNyb3Rhc2tCYXRjaERyaXZlcmAgaW5zdGVhZDtcbiAqIHRoaXMgZmFjdG9yeSBleGlzdHMgZm9yIHRlc3RzIGFuZCBmb3IgYWR2YW5jZWQgY29uc3VtZXJzIHdobyB3YW50IHRvXG4gKiBpbmplY3QgdGhlaXIgb3duIHJ1bm5lciAoZS5nLiwgYSBydW5uZXIgdGhhdCB3cmFwcyB0aGUgY2hpbGQgaW4gYVxuICogdHJhY2luZyBjb250ZXh0KS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZU1pY3JvdGFza0JhdGNoRHJpdmVyKHJ1bkNoaWxkOiBDaGlsZFJ1bm5lciA9IGRlZmF1bHRSdW5DaGlsZCk6IERldGFjaERyaXZlciB7XG4gIC8vIFBlci1kcml2ZXItaW5zdGFuY2UgcXVldWUgYW5kIGZsdXNoIGd1YXJkLiBDbG9zZWQgb3ZlciBieSBgc2NoZWR1bGVgXG4gIC8vIGFuZCBgZmx1c2hgIHNvIGVhY2ggY2FsbCB0byBgY3JlYXRlTWljcm90YXNrQmF0Y2hEcml2ZXJgIGdldHMgaXRzXG4gIC8vIG93biBpc29sYXRlZCBiYXRjaCAodGVzdCBpc29sYXRpb24sIG11bHRpLXRlbmFudCBzY2VuYXJpb3MpLlxuICBjb25zdCBxdWV1ZTogV29ya0l0ZW1bXSA9IFtdO1xuICBsZXQgc2NoZWR1bGVkID0gZmFsc2U7XG5cbiAgZnVuY3Rpb24gZmx1c2goKTogdm9pZCB7XG4gICAgLy8gUmVzZXQgQkVGT1JFIGRyYWluaW5nIHNvIHJlLWVudHJhbnQgc2NoZWR1bGUoKXMgZHVyaW5nIHJ1bkNoaWxkXG4gICAgLy8gcXVldWUgYSBmcmVzaCBtaWNyb3Rhc2sgaW5zdGVhZCBvZiBqb2luaW5nIHRoZSBpbi1mbGlnaHQgZHJhaW4uXG4gICAgc2NoZWR1bGVkID0gZmFsc2U7XG4gICAgY29uc3QgaXRlbXMgPSBxdWV1ZS5zcGxpY2UoMCk7XG4gICAgZm9yIChjb25zdCBpdGVtIG9mIGl0ZW1zKSB7XG4gICAgICAvLyBFYWNoIGl0ZW0gcnVucyBjb25jdXJyZW50bHkg4oCUIG5vIGF3YWl0cyBoZXJlLCBzbyB0aGUgb3V0ZXJcbiAgICAgIC8vIGZvci1sb29wIGNvbXBsZXRlcyB3aXRoaW4gdGhpcyBtaWNyb3Rhc2suIEVycm9ycyBpbnNpZGVcbiAgICAgIC8vIGBleGVjdXRlT25lYCBhcmUgcm91dGVkIHRvIHRoZSBoYW5kbGUsIG5vdCB0aHJvd24uIFRoZSBwcm9taXNlXG4gICAgICAvLyBpcyBpbnRlbnRpb25hbGx5IG5vdCBhd2FpdGVkOyBpZ25vcmUtcHJvbWlzZS1yZXR1cm5lZCB2aWEgdGhlXG4gICAgICAvLyBleHBsaWNpdCBuby1vcCAudGhlbigpIHBhdHRlcm4gdGhhdCB0aGUgcHJvamVjdCdzIGxpbnQgY29uZmlnXG4gICAgICAvLyBhY2NlcHRzICh2cyBgdm9pZGAsIHdoaWNoIGBuby12b2lkYCByZWplY3RzKS5cbiAgICAgIGV4ZWN1dGVPbmUoaXRlbSwgcnVuQ2hpbGQpLnRoZW4odW5kZWZpbmVkLCB1bmRlZmluZWQpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgbmFtZTogJ21pY3JvdGFzay1iYXRjaCcsXG4gICAgY2FwYWJpbGl0aWVzOiB7IGJyb3dzZXJTYWZlOiB0cnVlLCBub2RlU2FmZTogdHJ1ZSwgZWRnZVNhZmU6IHRydWUgfSxcbiAgICBzY2hlZHVsZShjaGlsZDogRmxvd0NoYXJ0LCBpbnB1dDogdW5rbm93biwgcmVmSWQ6IHN0cmluZyk6IERldGFjaEhhbmRsZSB7XG4gICAgICBjb25zdCBoYW5kbGUgPSBjcmVhdGVIYW5kbGUocmVmSWQpO1xuICAgICAgcmVnaXN0ZXIoaGFuZGxlKTtcbiAgICAgIHF1ZXVlLnB1c2goeyBjaGlsZCwgaW5wdXQsIGhhbmRsZSB9KTtcbiAgICAgIGlmICghc2NoZWR1bGVkKSB7XG4gICAgICAgIHNjaGVkdWxlZCA9IHRydWU7XG4gICAgICAgIHF1ZXVlTWljcm90YXNrKGZsdXNoKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBoYW5kbGU7XG4gICAgfSxcbiAgfTtcbn1cblxuLyoqXG4gKiBQZXItaXRlbSBleGVjdXRpb24uIE1hcmtzIHRoZSBoYW5kbGUgcnVubmluZywgYXdhaXRzIHRoZSBydW5uZXIsXG4gKiByb3V0ZXMgb3V0Y29tZSB0byB0aGUgaGFuZGxlLCBjbGVhbnMgdXAgdGhlIHJlZ2lzdHJ5IGVudHJ5LiBOZXZlclxuICogdGhyb3dzIOKAlCBlcnJvcnMgbGFuZCBvbiB0aGUgaGFuZGxlIChwYXNzaXZlIHJlY29yZGVyIHJ1bGUpLlxuICovXG5hc3luYyBmdW5jdGlvbiBleGVjdXRlT25lKGl0ZW06IFdvcmtJdGVtLCBydW5DaGlsZDogQ2hpbGRSdW5uZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgaW1wbCA9IGFzSW1wbChpdGVtLmhhbmRsZSk7XG4gIGltcGwuX21hcmtSdW5uaW5nKCk7XG4gIHRyeSB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcnVuQ2hpbGQoaXRlbS5jaGlsZCwgaXRlbS5pbnB1dCk7XG4gICAgaW1wbC5fbWFya0RvbmUocmVzdWx0KTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgaW1wbC5fbWFya0ZhaWxlZChlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyciA6IG5ldyBFcnJvcihTdHJpbmcoZXJyKSkpO1xuICB9IGZpbmFsbHkge1xuICAgIHVucmVnaXN0ZXIoaW1wbC5pZCk7XG4gIH1cbn1cblxuLyoqXG4gKiBEZWZhdWx0IHNpbmdsZXRvbi4gTW9zdCBjb25zdW1lcnMgaW1wb3J0IHRoaXMgYW5kIHBhc3MgaXQgdG9cbiAqIGBleGVjdXRvci5kZXRhY2hBbmRKb2luTGF0ZXIoY2hpbGQsIGlucHV0LCB7IGRyaXZlcjogbWljcm90YXNrQmF0Y2hEcml2ZXIgfSlgXG4gKiAob3IgcmVseSBvbiBpdCBiZWluZyB0aGUgZXhlY3V0b3IncyBkZWZhdWx0IGRyaXZlciwgc2V0IGluIFQ1YikuXG4gKi9cbmV4cG9ydCBjb25zdCBtaWNyb3Rhc2tCYXRjaERyaXZlcjogRGV0YWNoRHJpdmVyID0gY3JlYXRlTWljcm90YXNrQmF0Y2hEcml2ZXIoKTtcbiJdfQ==
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* detach/drivers/sendBeacon.ts — Browser-only driver that ships work
|
|
4
|
+
* via `navigator.sendBeacon` so it
|
|
5
|
+
* survives page-unload.
|
|
6
|
+
*
|
|
7
|
+
* Pattern: Strategy / Adapter — translates the consumer's child
|
|
8
|
+
* flowchart into a sendBeacon POST. The "child" is expected
|
|
9
|
+
* to produce a JSON-serializable payload via its
|
|
10
|
+
* `inputMapper`; the URL endpoint is set at driver creation.
|
|
11
|
+
* Role: The narrow but high-value driver for analytics / error
|
|
12
|
+
* reporting / page-leave telemetry — the one case where
|
|
13
|
+
* "fire-and-forget" must really mean "ships even if the
|
|
14
|
+
* user closes the tab right after."
|
|
15
|
+
*
|
|
16
|
+
* `navigator.sendBeacon` semantics:
|
|
17
|
+
* - Browser queues the POST in the OS network stack BEFORE returning
|
|
18
|
+
* control. Survives page-unload, navigation, refresh.
|
|
19
|
+
* - Limited to ~64 KB per call (per HTML5 spec).
|
|
20
|
+
* - Fire-and-forget — no response observable.
|
|
21
|
+
*
|
|
22
|
+
* Caveats:
|
|
23
|
+
* - Browser-only (`browserSafe: true, survivesUnload: true`).
|
|
24
|
+
* `validate()` throws helpfully if `navigator.sendBeacon` isn't a
|
|
25
|
+
* function (e.g., when imported in Node).
|
|
26
|
+
* - The driver does NOT run the child flowchart through a
|
|
27
|
+
* `FlowChartExecutor` — it serializes the input and POSTs. This
|
|
28
|
+
* is an intentional simplification: sendBeacon's semantics
|
|
29
|
+
* wouldn't survive an executor's async stages anyway.
|
|
30
|
+
*/
|
|
31
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
+
exports.createSendBeaconDriver = void 0;
|
|
33
|
+
const handle_js_1 = require("../handle.js");
|
|
34
|
+
const registry_js_1 = require("../registry.js");
|
|
35
|
+
function createSendBeaconDriver(opts) {
|
|
36
|
+
if (!opts.url) {
|
|
37
|
+
throw new TypeError('[detach] createSendBeaconDriver requires a `url` option.');
|
|
38
|
+
}
|
|
39
|
+
function serialize(input) {
|
|
40
|
+
if (opts.serialize)
|
|
41
|
+
return opts.serialize(input);
|
|
42
|
+
return new Blob([JSON.stringify(input ?? null)], { type: 'application/json' });
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
name: 'send-beacon',
|
|
46
|
+
capabilities: {
|
|
47
|
+
browserSafe: true,
|
|
48
|
+
survivesUnload: true,
|
|
49
|
+
},
|
|
50
|
+
validate() {
|
|
51
|
+
if (typeof navigator === 'undefined' || typeof navigator.sendBeacon !== 'function') {
|
|
52
|
+
throw new Error('[detach] sendBeaconDriver requires a browser environment with `navigator.sendBeacon`. ' +
|
|
53
|
+
'Use `microtaskBatchDriver` for in-process detach, or `setImmediateDriver` for Node.js.');
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
schedule(_child, input, refId) {
|
|
57
|
+
const handle = (0, handle_js_1.createHandle)(refId);
|
|
58
|
+
(0, registry_js_1.register)(handle);
|
|
59
|
+
const impl = (0, handle_js_1.asImpl)(handle);
|
|
60
|
+
impl._markRunning();
|
|
61
|
+
try {
|
|
62
|
+
const payload = serialize(input);
|
|
63
|
+
const accepted = navigator.sendBeacon(opts.url, payload);
|
|
64
|
+
if (accepted) {
|
|
65
|
+
impl._markDone({ accepted: true, url: opts.url });
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
impl._markFailed(new Error('[detach] navigator.sendBeacon refused the payload (likely over the ~64 KB limit).'));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
impl._markFailed(err instanceof Error ? err : new Error(String(err)));
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
(0, registry_js_1.unregister)(impl.id);
|
|
76
|
+
}
|
|
77
|
+
return handle;
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
exports.createSendBeaconDriver = createSendBeaconDriver;
|
|
82
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VuZEJlYWNvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvZGV0YWNoL2RyaXZlcnMvc2VuZEJlYWNvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E0Qkc7OztBQUdILDRDQUFvRDtBQUNwRCxnREFBc0Q7QUFXdEQsU0FBZ0Isc0JBQXNCLENBQUMsSUFBNkI7SUFDbEUsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUNkLE1BQU0sSUFBSSxTQUFTLENBQUMsMERBQTBELENBQUMsQ0FBQztJQUNsRixDQUFDO0lBRUQsU0FBUyxTQUFTLENBQUMsS0FBYztRQUMvQixJQUFJLElBQUksQ0FBQyxTQUFTO1lBQUUsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2pELE9BQU8sSUFBSSxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssSUFBSSxJQUFJLENBQUMsQ0FBQyxFQUFFLEVBQUUsSUFBSSxFQUFFLGtCQUFrQixFQUFFLENBQUMsQ0FBQztJQUNqRixDQUFDO0lBRUQsT0FBTztRQUNMLElBQUksRUFBRSxhQUFhO1FBQ25CLFlBQVksRUFBRTtZQUNaLFdBQVcsRUFBRSxJQUFJO1lBQ2pCLGNBQWMsRUFBRSxJQUFJO1NBQ3JCO1FBQ0QsUUFBUTtZQUNOLElBQUksT0FBTyxTQUFTLEtBQUssV0FBVyxJQUFJLE9BQU8sU0FBUyxDQUFDLFVBQVUsS0FBSyxVQUFVLEVBQUUsQ0FBQztnQkFDbkYsTUFBTSxJQUFJLEtBQUssQ0FDYix3RkFBd0Y7b0JBQ3RGLHdGQUF3RixDQUMzRixDQUFDO1lBQ0osQ0FBQztRQUNILENBQUM7UUFDRCxRQUFRLENBQUMsTUFBaUIsRUFBRSxLQUFjLEVBQUUsS0FBYTtZQUN2RCxNQUFNLE1BQU0sR0FBRyxJQUFBLHdCQUFZLEVBQUMsS0FBSyxDQUFDLENBQUM7WUFDbkMsSUFBQSxzQkFBUSxFQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ2pCLE1BQU0sSUFBSSxHQUFHLElBQUEsa0JBQU0sRUFBQyxNQUFNLENBQUMsQ0FBQztZQUM1QixJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDcEIsSUFBSSxDQUFDO2dCQUNILE1BQU0sT0FBTyxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDakMsTUFBTSxRQUFRLEdBQUcsU0FBUyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLE9BQW1CLENBQUMsQ0FBQztnQkFDckUsSUFBSSxRQUFRLEVBQUUsQ0FBQztvQkFDYixJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7Z0JBQ3BELENBQUM7cUJBQU0sQ0FBQztvQkFDTixJQUFJLENBQUMsV0FBVyxDQUNkLElBQUksS0FBSyxDQUFDLG1GQUFtRixDQUFDLENBQy9GLENBQUM7Z0JBQ0osQ0FBQztZQUNILENBQUM7WUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO2dCQUNiLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3hFLENBQUM7b0JBQVMsQ0FBQztnQkFDVCxJQUFBLHdCQUFVLEVBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ3RCLENBQUM7WUFDRCxPQUFPLE1BQU0sQ0FBQztRQUNoQixDQUFDO0tBQ0YsQ0FBQztBQUNKLENBQUM7QUEvQ0Qsd0RBK0NDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBkZXRhY2gvZHJpdmVycy9zZW5kQmVhY29uLnRzIOKAlCBCcm93c2VyLW9ubHkgZHJpdmVyIHRoYXQgc2hpcHMgd29ya1xuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpYSBgbmF2aWdhdG9yLnNlbmRCZWFjb25gIHNvIGl0XG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Vydml2ZXMgcGFnZS11bmxvYWQuXG4gKlxuICogUGF0dGVybjogIFN0cmF0ZWd5IC8gQWRhcHRlciDigJQgdHJhbnNsYXRlcyB0aGUgY29uc3VtZXIncyBjaGlsZFxuICogICAgICAgICAgIGZsb3djaGFydCBpbnRvIGEgc2VuZEJlYWNvbiBQT1NULiBUaGUgXCJjaGlsZFwiIGlzIGV4cGVjdGVkXG4gKiAgICAgICAgICAgdG8gcHJvZHVjZSBhIEpTT04tc2VyaWFsaXphYmxlIHBheWxvYWQgdmlhIGl0c1xuICogICAgICAgICAgIGBpbnB1dE1hcHBlcmA7IHRoZSBVUkwgZW5kcG9pbnQgaXMgc2V0IGF0IGRyaXZlciBjcmVhdGlvbi5cbiAqIFJvbGU6ICAgICBUaGUgbmFycm93IGJ1dCBoaWdoLXZhbHVlIGRyaXZlciBmb3IgYW5hbHl0aWNzIC8gZXJyb3JcbiAqICAgICAgICAgICByZXBvcnRpbmcgLyBwYWdlLWxlYXZlIHRlbGVtZXRyeSDigJQgdGhlIG9uZSBjYXNlIHdoZXJlXG4gKiAgICAgICAgICAgXCJmaXJlLWFuZC1mb3JnZXRcIiBtdXN0IHJlYWxseSBtZWFuIFwic2hpcHMgZXZlbiBpZiB0aGVcbiAqICAgICAgICAgICB1c2VyIGNsb3NlcyB0aGUgdGFiIHJpZ2h0IGFmdGVyLlwiXG4gKlxuICogYG5hdmlnYXRvci5zZW5kQmVhY29uYCBzZW1hbnRpY3M6XG4gKiAgIC0gQnJvd3NlciBxdWV1ZXMgdGhlIFBPU1QgaW4gdGhlIE9TIG5ldHdvcmsgc3RhY2sgQkVGT1JFIHJldHVybmluZ1xuICogICAgIGNvbnRyb2wuIFN1cnZpdmVzIHBhZ2UtdW5sb2FkLCBuYXZpZ2F0aW9uLCByZWZyZXNoLlxuICogICAtIExpbWl0ZWQgdG8gfjY0IEtCIHBlciBjYWxsIChwZXIgSFRNTDUgc3BlYykuXG4gKiAgIC0gRmlyZS1hbmQtZm9yZ2V0IOKAlCBubyByZXNwb25zZSBvYnNlcnZhYmxlLlxuICpcbiAqIENhdmVhdHM6XG4gKiAgIC0gQnJvd3Nlci1vbmx5IChgYnJvd3NlclNhZmU6IHRydWUsIHN1cnZpdmVzVW5sb2FkOiB0cnVlYCkuXG4gKiAgICAgYHZhbGlkYXRlKClgIHRocm93cyBoZWxwZnVsbHkgaWYgYG5hdmlnYXRvci5zZW5kQmVhY29uYCBpc24ndCBhXG4gKiAgICAgZnVuY3Rpb24gKGUuZy4sIHdoZW4gaW1wb3J0ZWQgaW4gTm9kZSkuXG4gKiAgIC0gVGhlIGRyaXZlciBkb2VzIE5PVCBydW4gdGhlIGNoaWxkIGZsb3djaGFydCB0aHJvdWdoIGFcbiAqICAgICBgRmxvd0NoYXJ0RXhlY3V0b3JgIOKAlCBpdCBzZXJpYWxpemVzIHRoZSBpbnB1dCBhbmQgUE9TVHMuIFRoaXNcbiAqICAgICBpcyBhbiBpbnRlbnRpb25hbCBzaW1wbGlmaWNhdGlvbjogc2VuZEJlYWNvbidzIHNlbWFudGljc1xuICogICAgIHdvdWxkbid0IHN1cnZpdmUgYW4gZXhlY3V0b3IncyBhc3luYyBzdGFnZXMgYW55d2F5LlxuICovXG5cbmltcG9ydCB0eXBlIHsgRmxvd0NoYXJ0IH0gZnJvbSAnLi4vLi4vYnVpbGRlci90eXBlcy5qcyc7XG5pbXBvcnQgeyBhc0ltcGwsIGNyZWF0ZUhhbmRsZSB9IGZyb20gJy4uL2hhbmRsZS5qcyc7XG5pbXBvcnQgeyByZWdpc3RlciwgdW5yZWdpc3RlciB9IGZyb20gJy4uL3JlZ2lzdHJ5LmpzJztcbmltcG9ydCB0eXBlIHsgRGV0YWNoRHJpdmVyLCBEZXRhY2hIYW5kbGUgfSBmcm9tICcuLi90eXBlcy5qcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2VuZEJlYWNvbkRyaXZlck9wdGlvbnMge1xuICAvKiogRW5kcG9pbnQgVVJMIOKAlCByZXF1aXJlZC4gZS5nLiwgYCdodHRwczovL3RlbGVtZXRyeS5leGFtcGxlLmNvbS9pbmdlc3QnYC4gKi9cbiAgcmVhZG9ubHkgdXJsOiBzdHJpbmc7XG4gIC8qKiBDdXN0b20gc2VyaWFsaXplci4gRGVmYXVsdHMgdG8gYEpTT04uc3RyaW5naWZ5KGlucHV0KWAgd2l0aFxuICAgKiAgYGFwcGxpY2F0aW9uL2pzb25gIGNvbnRlbnQgdHlwZS4gKi9cbiAgcmVhZG9ubHkgc2VyaWFsaXplPzogKGlucHV0OiB1bmtub3duKSA9PiBCbG9iIHwgc3RyaW5nIHwgRm9ybURhdGE7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTZW5kQmVhY29uRHJpdmVyKG9wdHM6IFNlbmRCZWFjb25Ecml2ZXJPcHRpb25zKTogRGV0YWNoRHJpdmVyIHtcbiAgaWYgKCFvcHRzLnVybCkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1tkZXRhY2hdIGNyZWF0ZVNlbmRCZWFjb25Ecml2ZXIgcmVxdWlyZXMgYSBgdXJsYCBvcHRpb24uJyk7XG4gIH1cblxuICBmdW5jdGlvbiBzZXJpYWxpemUoaW5wdXQ6IHVua25vd24pOiBCbG9iIHwgc3RyaW5nIHwgRm9ybURhdGEge1xuICAgIGlmIChvcHRzLnNlcmlhbGl6ZSkgcmV0dXJuIG9wdHMuc2VyaWFsaXplKGlucHV0KTtcbiAgICByZXR1cm4gbmV3IEJsb2IoW0pTT04uc3RyaW5naWZ5KGlucHV0ID8/IG51bGwpXSwgeyB0eXBlOiAnYXBwbGljYXRpb24vanNvbicgfSk7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIG5hbWU6ICdzZW5kLWJlYWNvbicsXG4gICAgY2FwYWJpbGl0aWVzOiB7XG4gICAgICBicm93c2VyU2FmZTogdHJ1ZSxcbiAgICAgIHN1cnZpdmVzVW5sb2FkOiB0cnVlLFxuICAgIH0sXG4gICAgdmFsaWRhdGUoKTogdm9pZCB7XG4gICAgICBpZiAodHlwZW9mIG5hdmlnYXRvciA9PT0gJ3VuZGVmaW5lZCcgfHwgdHlwZW9mIG5hdmlnYXRvci5zZW5kQmVhY29uICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAnW2RldGFjaF0gc2VuZEJlYWNvbkRyaXZlciByZXF1aXJlcyBhIGJyb3dzZXIgZW52aXJvbm1lbnQgd2l0aCBgbmF2aWdhdG9yLnNlbmRCZWFjb25gLiAnICtcbiAgICAgICAgICAgICdVc2UgYG1pY3JvdGFza0JhdGNoRHJpdmVyYCBmb3IgaW4tcHJvY2VzcyBkZXRhY2gsIG9yIGBzZXRJbW1lZGlhdGVEcml2ZXJgIGZvciBOb2RlLmpzLicsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSxcbiAgICBzY2hlZHVsZShfY2hpbGQ6IEZsb3dDaGFydCwgaW5wdXQ6IHVua25vd24sIHJlZklkOiBzdHJpbmcpOiBEZXRhY2hIYW5kbGUge1xuICAgICAgY29uc3QgaGFuZGxlID0gY3JlYXRlSGFuZGxlKHJlZklkKTtcbiAgICAgIHJlZ2lzdGVyKGhhbmRsZSk7XG4gICAgICBjb25zdCBpbXBsID0gYXNJbXBsKGhhbmRsZSk7XG4gICAgICBpbXBsLl9tYXJrUnVubmluZygpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcGF5bG9hZCA9IHNlcmlhbGl6ZShpbnB1dCk7XG4gICAgICAgIGNvbnN0IGFjY2VwdGVkID0gbmF2aWdhdG9yLnNlbmRCZWFjb24ob3B0cy51cmwsIHBheWxvYWQgYXMgQm9keUluaXQpO1xuICAgICAgICBpZiAoYWNjZXB0ZWQpIHtcbiAgICAgICAgICBpbXBsLl9tYXJrRG9uZSh7IGFjY2VwdGVkOiB0cnVlLCB1cmw6IG9wdHMudXJsIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGltcGwuX21hcmtGYWlsZWQoXG4gICAgICAgICAgICBuZXcgRXJyb3IoJ1tkZXRhY2hdIG5hdmlnYXRvci5zZW5kQmVhY29uIHJlZnVzZWQgdGhlIHBheWxvYWQgKGxpa2VseSBvdmVyIHRoZSB+NjQgS0IgbGltaXQpLicpLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBpbXBsLl9tYXJrRmFpbGVkKGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyIDogbmV3IEVycm9yKFN0cmluZyhlcnIpKSk7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICB1bnJlZ2lzdGVyKGltcGwuaWQpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGhhbmRsZTtcbiAgICB9LFxuICB9O1xufVxuIl19
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* detach/drivers/setImmediate.ts — Defer detached work to a Node.js
|
|
4
|
+
* `setImmediate` boundary.
|
|
5
|
+
*
|
|
6
|
+
* Pattern: Same producer-consumer batch flush as `microtaskBatch`,
|
|
7
|
+
* but the deferral is `setImmediate` instead of
|
|
8
|
+
* `queueMicrotask`. Yields control back to the event loop
|
|
9
|
+
* BEFORE running — allows pending I/O callbacks to drain
|
|
10
|
+
* first, which microtasks would block.
|
|
11
|
+
* Role: Node-specific driver for "fire-and-forget after the
|
|
12
|
+
* current I/O tick." Use when the parent stage handles
|
|
13
|
+
* latency-sensitive work and you don't want detached work
|
|
14
|
+
* to compete for the synchronous slice.
|
|
15
|
+
*
|
|
16
|
+
* When to pick this over microtaskBatch:
|
|
17
|
+
* - You're shipping logs / metrics in a hot HTTP path and don't
|
|
18
|
+
* want them blocking the response from being flushed
|
|
19
|
+
* - The detached work itself is CPU-heavy enough that running it on
|
|
20
|
+
* the same microtask cycle would delay other microtasks
|
|
21
|
+
* - You explicitly want "next event-loop tick" semantics — useful
|
|
22
|
+
* when interacting with third-party libraries that expect at
|
|
23
|
+
* least one I/O tick between schedule and execution
|
|
24
|
+
*
|
|
25
|
+
* Capability:
|
|
26
|
+
* - `nodeSafe: true` — relies on Node's `setImmediate`, NOT
|
|
27
|
+
* available in browsers / Deno / Cloudflare Workers (use
|
|
28
|
+
* `setTimeoutDriver` for cross-runtime alternative)
|
|
29
|
+
*/
|
|
30
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
|
+
exports.setImmediateDriver = exports.createSetImmediateDriver = void 0;
|
|
32
|
+
const handle_js_1 = require("../handle.js");
|
|
33
|
+
const registry_js_1 = require("../registry.js");
|
|
34
|
+
const runChild_js_1 = require("../runChild.js");
|
|
35
|
+
function createSetImmediateDriver(runChild = runChild_js_1.defaultRunChild) {
|
|
36
|
+
const queue = [];
|
|
37
|
+
let scheduled = false;
|
|
38
|
+
function flush() {
|
|
39
|
+
scheduled = false;
|
|
40
|
+
const items = queue.splice(0);
|
|
41
|
+
for (const item of items) {
|
|
42
|
+
executeOne(item, runChild).then(undefined, undefined);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
name: 'set-immediate',
|
|
47
|
+
capabilities: { nodeSafe: true },
|
|
48
|
+
validate() {
|
|
49
|
+
if (typeof setImmediate !== 'function') {
|
|
50
|
+
throw new Error('[detach] setImmediateDriver requires Node.js — global `setImmediate` is not defined ' +
|
|
51
|
+
'in this runtime. Use `microtaskBatchDriver` for cross-runtime use, or `setTimeoutDriver` ' +
|
|
52
|
+
'for browser/edge environments.');
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
schedule(child, input, refId) {
|
|
56
|
+
const handle = (0, handle_js_1.createHandle)(refId);
|
|
57
|
+
(0, registry_js_1.register)(handle);
|
|
58
|
+
queue.push({ child, input, handle });
|
|
59
|
+
if (!scheduled) {
|
|
60
|
+
scheduled = true;
|
|
61
|
+
// `setImmediate` is non-undefined here in Node; runtime guard
|
|
62
|
+
// is in `validate()`. The `!` is a deliberate assertion.
|
|
63
|
+
setImmediate(flush);
|
|
64
|
+
}
|
|
65
|
+
return handle;
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
exports.createSetImmediateDriver = createSetImmediateDriver;
|
|
70
|
+
async function executeOne(item, runChild) {
|
|
71
|
+
const impl = (0, handle_js_1.asImpl)(item.handle);
|
|
72
|
+
impl._markRunning();
|
|
73
|
+
try {
|
|
74
|
+
const result = await runChild(item.child, item.input);
|
|
75
|
+
impl._markDone(result);
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
impl._markFailed(err instanceof Error ? err : new Error(String(err)));
|
|
79
|
+
}
|
|
80
|
+
finally {
|
|
81
|
+
(0, registry_js_1.unregister)(impl.id);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.setImmediateDriver = createSetImmediateDriver();
|
|
85
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2V0SW1tZWRpYXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9kZXRhY2gvZHJpdmVycy9zZXRJbW1lZGlhdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0EyQkc7OztBQUdILDRDQUFvRDtBQUNwRCxnREFBc0Q7QUFDdEQsZ0RBQW1FO0FBZW5FLFNBQWdCLHdCQUF3QixDQUFDLFdBQXdCLDZCQUFlO0lBQzlFLE1BQU0sS0FBSyxHQUFlLEVBQUUsQ0FBQztJQUM3QixJQUFJLFNBQVMsR0FBRyxLQUFLLENBQUM7SUFFdEIsU0FBUyxLQUFLO1FBQ1osU0FBUyxHQUFHLEtBQUssQ0FBQztRQUNsQixNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzlCLEtBQUssTUFBTSxJQUFJLElBQUksS0FBSyxFQUFFLENBQUM7WUFDekIsVUFBVSxDQUFDLElBQUksRUFBRSxRQUFRLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQ3hELENBQUM7SUFDSCxDQUFDO0lBRUQsT0FBTztRQUNMLElBQUksRUFBRSxlQUFlO1FBQ3JCLFlBQVksRUFBRSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUU7UUFDaEMsUUFBUTtZQUNOLElBQUksT0FBTyxZQUFZLEtBQUssVUFBVSxFQUFFLENBQUM7Z0JBQ3ZDLE1BQU0sSUFBSSxLQUFLLENBQ2Isc0ZBQXNGO29CQUNwRiwyRkFBMkY7b0JBQzNGLGdDQUFnQyxDQUNuQyxDQUFDO1lBQ0osQ0FBQztRQUNILENBQUM7UUFDRCxRQUFRLENBQUMsS0FBZ0IsRUFBRSxLQUFjLEVBQUUsS0FBYTtZQUN0RCxNQUFNLE1BQU0sR0FBRyxJQUFBLHdCQUFZLEVBQUMsS0FBSyxDQUFDLENBQUM7WUFDbkMsSUFBQSxzQkFBUSxFQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ2pCLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUM7WUFDckMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO2dCQUNmLFNBQVMsR0FBRyxJQUFJLENBQUM7Z0JBQ2pCLDhEQUE4RDtnQkFDOUQseURBQXlEO2dCQUN6RCxZQUFhLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDdkIsQ0FBQztZQUNELE9BQU8sTUFBTSxDQUFDO1FBQ2hCLENBQUM7S0FDRixDQUFDO0FBQ0osQ0FBQztBQXJDRCw0REFxQ0M7QUFFRCxLQUFLLFVBQVUsVUFBVSxDQUFDLElBQWMsRUFBRSxRQUFxQjtJQUM3RCxNQUFNLElBQUksR0FBRyxJQUFBLGtCQUFNLEVBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ2pDLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUNwQixJQUFJLENBQUM7UUFDSCxNQUFNLE1BQU0sR0FBRyxNQUFNLFFBQVEsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN0RCxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3pCLENBQUM7SUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1FBQ2IsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDeEUsQ0FBQztZQUFTLENBQUM7UUFDVCxJQUFBLHdCQUFVLEVBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3RCLENBQUM7QUFDSCxDQUFDO0FBRVksUUFBQSxrQkFBa0IsR0FBaUIsd0JBQXdCLEVBQUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogZGV0YWNoL2RyaXZlcnMvc2V0SW1tZWRpYXRlLnRzIOKAlCBEZWZlciBkZXRhY2hlZCB3b3JrIHRvIGEgTm9kZS5qc1xuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYHNldEltbWVkaWF0ZWAgYm91bmRhcnkuXG4gKlxuICogUGF0dGVybjogIFNhbWUgcHJvZHVjZXItY29uc3VtZXIgYmF0Y2ggZmx1c2ggYXMgYG1pY3JvdGFza0JhdGNoYCxcbiAqICAgICAgICAgICBidXQgdGhlIGRlZmVycmFsIGlzIGBzZXRJbW1lZGlhdGVgIGluc3RlYWQgb2ZcbiAqICAgICAgICAgICBgcXVldWVNaWNyb3Rhc2tgLiBZaWVsZHMgY29udHJvbCBiYWNrIHRvIHRoZSBldmVudCBsb29wXG4gKiAgICAgICAgICAgQkVGT1JFIHJ1bm5pbmcg4oCUIGFsbG93cyBwZW5kaW5nIEkvTyBjYWxsYmFja3MgdG8gZHJhaW5cbiAqICAgICAgICAgICBmaXJzdCwgd2hpY2ggbWljcm90YXNrcyB3b3VsZCBibG9jay5cbiAqIFJvbGU6ICAgICBOb2RlLXNwZWNpZmljIGRyaXZlciBmb3IgXCJmaXJlLWFuZC1mb3JnZXQgYWZ0ZXIgdGhlXG4gKiAgICAgICAgICAgY3VycmVudCBJL08gdGljay5cIiBVc2Ugd2hlbiB0aGUgcGFyZW50IHN0YWdlIGhhbmRsZXNcbiAqICAgICAgICAgICBsYXRlbmN5LXNlbnNpdGl2ZSB3b3JrIGFuZCB5b3UgZG9uJ3Qgd2FudCBkZXRhY2hlZCB3b3JrXG4gKiAgICAgICAgICAgdG8gY29tcGV0ZSBmb3IgdGhlIHN5bmNocm9ub3VzIHNsaWNlLlxuICpcbiAqIFdoZW4gdG8gcGljayB0aGlzIG92ZXIgbWljcm90YXNrQmF0Y2g6XG4gKiAgIC0gWW91J3JlIHNoaXBwaW5nIGxvZ3MgLyBtZXRyaWNzIGluIGEgaG90IEhUVFAgcGF0aCBhbmQgZG9uJ3RcbiAqICAgICB3YW50IHRoZW0gYmxvY2tpbmcgdGhlIHJlc3BvbnNlIGZyb20gYmVpbmcgZmx1c2hlZFxuICogICAtIFRoZSBkZXRhY2hlZCB3b3JrIGl0c2VsZiBpcyBDUFUtaGVhdnkgZW5vdWdoIHRoYXQgcnVubmluZyBpdCBvblxuICogICAgIHRoZSBzYW1lIG1pY3JvdGFzayBjeWNsZSB3b3VsZCBkZWxheSBvdGhlciBtaWNyb3Rhc2tzXG4gKiAgIC0gWW91IGV4cGxpY2l0bHkgd2FudCBcIm5leHQgZXZlbnQtbG9vcCB0aWNrXCIgc2VtYW50aWNzIOKAlCB1c2VmdWxcbiAqICAgICB3aGVuIGludGVyYWN0aW5nIHdpdGggdGhpcmQtcGFydHkgbGlicmFyaWVzIHRoYXQgZXhwZWN0IGF0XG4gKiAgICAgbGVhc3Qgb25lIEkvTyB0aWNrIGJldHdlZW4gc2NoZWR1bGUgYW5kIGV4ZWN1dGlvblxuICpcbiAqIENhcGFiaWxpdHk6XG4gKiAgIC0gYG5vZGVTYWZlOiB0cnVlYCDigJQgcmVsaWVzIG9uIE5vZGUncyBgc2V0SW1tZWRpYXRlYCwgTk9UXG4gKiAgICAgYXZhaWxhYmxlIGluIGJyb3dzZXJzIC8gRGVubyAvIENsb3VkZmxhcmUgV29ya2VycyAodXNlXG4gKiAgICAgYHNldFRpbWVvdXREcml2ZXJgIGZvciBjcm9zcy1ydW50aW1lIGFsdGVybmF0aXZlKVxuICovXG5cbmltcG9ydCB0eXBlIHsgRmxvd0NoYXJ0IH0gZnJvbSAnLi4vLi4vYnVpbGRlci90eXBlcy5qcyc7XG5pbXBvcnQgeyBhc0ltcGwsIGNyZWF0ZUhhbmRsZSB9IGZyb20gJy4uL2hhbmRsZS5qcyc7XG5pbXBvcnQgeyByZWdpc3RlciwgdW5yZWdpc3RlciB9IGZyb20gJy4uL3JlZ2lzdHJ5LmpzJztcbmltcG9ydCB7IHR5cGUgQ2hpbGRSdW5uZXIsIGRlZmF1bHRSdW5DaGlsZCB9IGZyb20gJy4uL3J1bkNoaWxkLmpzJztcbmltcG9ydCB0eXBlIHsgRGV0YWNoRHJpdmVyLCBEZXRhY2hIYW5kbGUgfSBmcm9tICcuLi90eXBlcy5qcyc7XG5cbi8vIE5vZGUtb25seSBnbG9iYWwuIFdlIGRvbid0IHNoaXAgQHR5cGVzL25vZGUsIHNvIGRlY2xhcmUgdGhlIG1pbmltYWxcbi8vIHNoYXBlIGhlcmUuIGBzZXRJbW1lZGlhdGVEcml2ZXJgIGFkdmVydGlzZXMgYG5vZGVTYWZlOiB0cnVlYCBhbmRcbi8vIGB2YWxpZGF0ZSgpYCB0aHJvd3MgaGVscGZ1bGx5IGlmIGBzZXRJbW1lZGlhdGVgIGlzIHVuZGVmaW5lZCBhdCB1c2Vcbi8vIHRpbWUgKGUuZy4sIGJyb3dzZXIgYnVuZGxlKS5cbmRlY2xhcmUgY29uc3Qgc2V0SW1tZWRpYXRlOiAoKGNiOiAoKSA9PiB2b2lkKSA9PiB1bmtub3duKSB8IHVuZGVmaW5lZDtcblxuaW50ZXJmYWNlIFdvcmtJdGVtIHtcbiAgcmVhZG9ubHkgY2hpbGQ6IEZsb3dDaGFydDtcbiAgcmVhZG9ubHkgaW5wdXQ6IHVua25vd247XG4gIHJlYWRvbmx5IGhhbmRsZTogRGV0YWNoSGFuZGxlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlU2V0SW1tZWRpYXRlRHJpdmVyKHJ1bkNoaWxkOiBDaGlsZFJ1bm5lciA9IGRlZmF1bHRSdW5DaGlsZCk6IERldGFjaERyaXZlciB7XG4gIGNvbnN0IHF1ZXVlOiBXb3JrSXRlbVtdID0gW107XG4gIGxldCBzY2hlZHVsZWQgPSBmYWxzZTtcblxuICBmdW5jdGlvbiBmbHVzaCgpOiB2b2lkIHtcbiAgICBzY2hlZHVsZWQgPSBmYWxzZTtcbiAgICBjb25zdCBpdGVtcyA9IHF1ZXVlLnNwbGljZSgwKTtcbiAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgaXRlbXMpIHtcbiAgICAgIGV4ZWN1dGVPbmUoaXRlbSwgcnVuQ2hpbGQpLnRoZW4odW5kZWZpbmVkLCB1bmRlZmluZWQpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgbmFtZTogJ3NldC1pbW1lZGlhdGUnLFxuICAgIGNhcGFiaWxpdGllczogeyBub2RlU2FmZTogdHJ1ZSB9LFxuICAgIHZhbGlkYXRlKCk6IHZvaWQge1xuICAgICAgaWYgKHR5cGVvZiBzZXRJbW1lZGlhdGUgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICdbZGV0YWNoXSBzZXRJbW1lZGlhdGVEcml2ZXIgcmVxdWlyZXMgTm9kZS5qcyDigJQgZ2xvYmFsIGBzZXRJbW1lZGlhdGVgIGlzIG5vdCBkZWZpbmVkICcgK1xuICAgICAgICAgICAgJ2luIHRoaXMgcnVudGltZS4gVXNlIGBtaWNyb3Rhc2tCYXRjaERyaXZlcmAgZm9yIGNyb3NzLXJ1bnRpbWUgdXNlLCBvciBgc2V0VGltZW91dERyaXZlcmAgJyArXG4gICAgICAgICAgICAnZm9yIGJyb3dzZXIvZWRnZSBlbnZpcm9ubWVudHMuJyxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIHNjaGVkdWxlKGNoaWxkOiBGbG93Q2hhcnQsIGlucHV0OiB1bmtub3duLCByZWZJZDogc3RyaW5nKTogRGV0YWNoSGFuZGxlIHtcbiAgICAgIGNvbnN0IGhhbmRsZSA9IGNyZWF0ZUhhbmRsZShyZWZJZCk7XG4gICAgICByZWdpc3RlcihoYW5kbGUpO1xuICAgICAgcXVldWUucHVzaCh7IGNoaWxkLCBpbnB1dCwgaGFuZGxlIH0pO1xuICAgICAgaWYgKCFzY2hlZHVsZWQpIHtcbiAgICAgICAgc2NoZWR1bGVkID0gdHJ1ZTtcbiAgICAgICAgLy8gYHNldEltbWVkaWF0ZWAgaXMgbm9uLXVuZGVmaW5lZCBoZXJlIGluIE5vZGU7IHJ1bnRpbWUgZ3VhcmRcbiAgICAgICAgLy8gaXMgaW4gYHZhbGlkYXRlKClgLiBUaGUgYCFgIGlzIGEgZGVsaWJlcmF0ZSBhc3NlcnRpb24uXG4gICAgICAgIHNldEltbWVkaWF0ZSEoZmx1c2gpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGhhbmRsZTtcbiAgICB9LFxuICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBleGVjdXRlT25lKGl0ZW06IFdvcmtJdGVtLCBydW5DaGlsZDogQ2hpbGRSdW5uZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgaW1wbCA9IGFzSW1wbChpdGVtLmhhbmRsZSk7XG4gIGltcGwuX21hcmtSdW5uaW5nKCk7XG4gIHRyeSB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcnVuQ2hpbGQoaXRlbS5jaGlsZCwgaXRlbS5pbnB1dCk7XG4gICAgaW1wbC5fbWFya0RvbmUocmVzdWx0KTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgaW1wbC5fbWFya0ZhaWxlZChlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyciA6IG5ldyBFcnJvcihTdHJpbmcoZXJyKSkpO1xuICB9IGZpbmFsbHkge1xuICAgIHVucmVnaXN0ZXIoaW1wbC5pZCk7XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IHNldEltbWVkaWF0ZURyaXZlcjogRGV0YWNoRHJpdmVyID0gY3JlYXRlU2V0SW1tZWRpYXRlRHJpdmVyKCk7XG4iXX0=
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* detach/drivers/setTimeout.ts — Defer detached work via `setTimeout(..., delayMs)`.
|
|
4
|
+
*
|
|
5
|
+
* Pattern: Producer-consumer batch flush; deferral mechanism is
|
|
6
|
+
* `setTimeout` with a configurable delay (default `0`).
|
|
7
|
+
* Role: Cross-runtime "next macrotask" driver. Works in browsers,
|
|
8
|
+
* Node.js, Deno, Cloudflare Workers, Bun, etc.
|
|
9
|
+
*
|
|
10
|
+
* When to pick this:
|
|
11
|
+
* - Consumer wants a SPECIFIC delay (e.g. "ship telemetry in 5
|
|
12
|
+
* seconds, batched") — pass `createSetTimeoutDriver({ delayMs: 5000 })`
|
|
13
|
+
* - Cross-runtime detach where `setImmediate` isn't available
|
|
14
|
+
* - Coalescing high-frequency events into a low-frequency flush
|
|
15
|
+
*
|
|
16
|
+
* Caveats:
|
|
17
|
+
* - Not for low-latency hot paths — minimum delay is ~4ms in
|
|
18
|
+
* browsers per the HTML5 spec, ~1ms in Node. Use
|
|
19
|
+
* `microtaskBatchDriver` for sub-ms scheduling.
|
|
20
|
+
* - Browser tab freezing / throttling can extend the delay
|
|
21
|
+
* significantly. Don't rely on precise timing.
|
|
22
|
+
*/
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
exports.setTimeoutDriver = exports.createSetTimeoutDriver = void 0;
|
|
25
|
+
const handle_js_1 = require("../handle.js");
|
|
26
|
+
const registry_js_1 = require("../registry.js");
|
|
27
|
+
const runChild_js_1 = require("../runChild.js");
|
|
28
|
+
function createSetTimeoutDriver(opts = {}) {
|
|
29
|
+
const delayMs = opts.delayMs ?? 0;
|
|
30
|
+
const runChild = opts.runChild ?? runChild_js_1.defaultRunChild;
|
|
31
|
+
const queue = [];
|
|
32
|
+
let scheduled = false;
|
|
33
|
+
function flush() {
|
|
34
|
+
scheduled = false;
|
|
35
|
+
const items = queue.splice(0);
|
|
36
|
+
for (const item of items) {
|
|
37
|
+
executeOne(item, runChild).then(undefined, undefined);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
name: delayMs === 0 ? 'set-timeout' : `set-timeout-${delayMs}ms`,
|
|
42
|
+
capabilities: { browserSafe: true, nodeSafe: true, edgeSafe: true },
|
|
43
|
+
schedule(child, input, refId) {
|
|
44
|
+
const handle = (0, handle_js_1.createHandle)(refId);
|
|
45
|
+
(0, registry_js_1.register)(handle);
|
|
46
|
+
queue.push({ child, input, handle });
|
|
47
|
+
if (!scheduled) {
|
|
48
|
+
scheduled = true;
|
|
49
|
+
setTimeout(flush, delayMs);
|
|
50
|
+
}
|
|
51
|
+
return handle;
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
exports.createSetTimeoutDriver = createSetTimeoutDriver;
|
|
56
|
+
async function executeOne(item, runChild) {
|
|
57
|
+
const impl = (0, handle_js_1.asImpl)(item.handle);
|
|
58
|
+
impl._markRunning();
|
|
59
|
+
try {
|
|
60
|
+
const result = await runChild(item.child, item.input);
|
|
61
|
+
impl._markDone(result);
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
impl._markFailed(err instanceof Error ? err : new Error(String(err)));
|
|
65
|
+
}
|
|
66
|
+
finally {
|
|
67
|
+
(0, registry_js_1.unregister)(impl.id);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/** Default singleton — zero-delay (next macrotask). For configurable
|
|
71
|
+
* delays, use `createSetTimeoutDriver({ delayMs })`. */
|
|
72
|
+
exports.setTimeoutDriver = createSetTimeoutDriver();
|
|
73
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2V0VGltZW91dC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvZGV0YWNoL2RyaXZlcnMvc2V0VGltZW91dC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBb0JHOzs7QUFHSCw0Q0FBb0Q7QUFDcEQsZ0RBQXNEO0FBQ3RELGdEQUFtRTtBQWlCbkUsU0FBZ0Isc0JBQXNCLENBQUMsT0FBZ0MsRUFBRTtJQUN2RSxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxJQUFJLENBQUMsQ0FBQztJQUNsQyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBUSxJQUFJLDZCQUFlLENBQUM7SUFDbEQsTUFBTSxLQUFLLEdBQWUsRUFBRSxDQUFDO0lBQzdCLElBQUksU0FBUyxHQUFHLEtBQUssQ0FBQztJQUV0QixTQUFTLEtBQUs7UUFDWixTQUFTLEdBQUcsS0FBSyxDQUFDO1FBQ2xCLE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDOUIsS0FBSyxNQUFNLElBQUksSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUN6QixVQUFVLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDeEQsQ0FBQztJQUNILENBQUM7SUFFRCxPQUFPO1FBQ0wsSUFBSSxFQUFFLE9BQU8sS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsZUFBZSxPQUFPLElBQUk7UUFDaEUsWUFBWSxFQUFFLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUU7UUFDbkUsUUFBUSxDQUFDLEtBQWdCLEVBQUUsS0FBYyxFQUFFLEtBQWE7WUFDdEQsTUFBTSxNQUFNLEdBQUcsSUFBQSx3QkFBWSxFQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ25DLElBQUEsc0JBQVEsRUFBQyxNQUFNLENBQUMsQ0FBQztZQUNqQixLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO1lBQ3JDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztnQkFDZixTQUFTLEdBQUcsSUFBSSxDQUFDO2dCQUNqQixVQUFVLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQzdCLENBQUM7WUFDRCxPQUFPLE1BQU0sQ0FBQztRQUNoQixDQUFDO0tBQ0YsQ0FBQztBQUNKLENBQUM7QUE1QkQsd0RBNEJDO0FBRUQsS0FBSyxVQUFVLFVBQVUsQ0FBQyxJQUFjLEVBQUUsUUFBcUI7SUFDN0QsTUFBTSxJQUFJLEdBQUcsSUFBQSxrQkFBTSxFQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNqQyxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDcEIsSUFBSSxDQUFDO1FBQ0gsTUFBTSxNQUFNLEdBQUcsTUFBTSxRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDdEQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN6QixDQUFDO0lBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUNiLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hFLENBQUM7WUFBUyxDQUFDO1FBQ1QsSUFBQSx3QkFBVSxFQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUN0QixDQUFDO0FBQ0gsQ0FBQztBQUVEO3lEQUN5RDtBQUM1QyxRQUFBLGdCQUFnQixHQUFpQixzQkFBc0IsRUFBRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBkZXRhY2gvZHJpdmVycy9zZXRUaW1lb3V0LnRzIOKAlCBEZWZlciBkZXRhY2hlZCB3b3JrIHZpYSBgc2V0VGltZW91dCguLi4sIGRlbGF5TXMpYC5cbiAqXG4gKiBQYXR0ZXJuOiAgUHJvZHVjZXItY29uc3VtZXIgYmF0Y2ggZmx1c2g7IGRlZmVycmFsIG1lY2hhbmlzbSBpc1xuICogICAgICAgICAgIGBzZXRUaW1lb3V0YCB3aXRoIGEgY29uZmlndXJhYmxlIGRlbGF5IChkZWZhdWx0IGAwYCkuXG4gKiBSb2xlOiAgICAgQ3Jvc3MtcnVudGltZSBcIm5leHQgbWFjcm90YXNrXCIgZHJpdmVyLiBXb3JrcyBpbiBicm93c2VycyxcbiAqICAgICAgICAgICBOb2RlLmpzLCBEZW5vLCBDbG91ZGZsYXJlIFdvcmtlcnMsIEJ1biwgZXRjLlxuICpcbiAqIFdoZW4gdG8gcGljayB0aGlzOlxuICogICAtIENvbnN1bWVyIHdhbnRzIGEgU1BFQ0lGSUMgZGVsYXkgKGUuZy4gXCJzaGlwIHRlbGVtZXRyeSBpbiA1XG4gKiAgICAgc2Vjb25kcywgYmF0Y2hlZFwiKSDigJQgcGFzcyBgY3JlYXRlU2V0VGltZW91dERyaXZlcih7IGRlbGF5TXM6IDUwMDAgfSlgXG4gKiAgIC0gQ3Jvc3MtcnVudGltZSBkZXRhY2ggd2hlcmUgYHNldEltbWVkaWF0ZWAgaXNuJ3QgYXZhaWxhYmxlXG4gKiAgIC0gQ29hbGVzY2luZyBoaWdoLWZyZXF1ZW5jeSBldmVudHMgaW50byBhIGxvdy1mcmVxdWVuY3kgZmx1c2hcbiAqXG4gKiBDYXZlYXRzOlxuICogICAtIE5vdCBmb3IgbG93LWxhdGVuY3kgaG90IHBhdGhzIOKAlCBtaW5pbXVtIGRlbGF5IGlzIH40bXMgaW5cbiAqICAgICBicm93c2VycyBwZXIgdGhlIEhUTUw1IHNwZWMsIH4xbXMgaW4gTm9kZS4gVXNlXG4gKiAgICAgYG1pY3JvdGFza0JhdGNoRHJpdmVyYCBmb3Igc3ViLW1zIHNjaGVkdWxpbmcuXG4gKiAgIC0gQnJvd3NlciB0YWIgZnJlZXppbmcgLyB0aHJvdHRsaW5nIGNhbiBleHRlbmQgdGhlIGRlbGF5XG4gKiAgICAgc2lnbmlmaWNhbnRseS4gRG9uJ3QgcmVseSBvbiBwcmVjaXNlIHRpbWluZy5cbiAqL1xuXG5pbXBvcnQgdHlwZSB7IEZsb3dDaGFydCB9IGZyb20gJy4uLy4uL2J1aWxkZXIvdHlwZXMuanMnO1xuaW1wb3J0IHsgYXNJbXBsLCBjcmVhdGVIYW5kbGUgfSBmcm9tICcuLi9oYW5kbGUuanMnO1xuaW1wb3J0IHsgcmVnaXN0ZXIsIHVucmVnaXN0ZXIgfSBmcm9tICcuLi9yZWdpc3RyeS5qcyc7XG5pbXBvcnQgeyB0eXBlIENoaWxkUnVubmVyLCBkZWZhdWx0UnVuQ2hpbGQgfSBmcm9tICcuLi9ydW5DaGlsZC5qcyc7XG5pbXBvcnQgdHlwZSB7IERldGFjaERyaXZlciwgRGV0YWNoSGFuZGxlIH0gZnJvbSAnLi4vdHlwZXMuanMnO1xuXG5pbnRlcmZhY2UgV29ya0l0ZW0ge1xuICByZWFkb25seSBjaGlsZDogRmxvd0NoYXJ0O1xuICByZWFkb25seSBpbnB1dDogdW5rbm93bjtcbiAgcmVhZG9ubHkgaGFuZGxlOiBEZXRhY2hIYW5kbGU7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2V0VGltZW91dERyaXZlck9wdGlvbnMge1xuICAvKiogTWlsbGlzZWNvbmRzIHRvIHdhaXQgYmVmb3JlIGZsdXNoaW5nIHRoZSBiYXRjaC4gRGVmYXVsdCAwXG4gICAqICAobmV4dCBtYWNyb3Rhc2spLiAqL1xuICByZWFkb25seSBkZWxheU1zPzogbnVtYmVyO1xuICAvKiogQ3VzdG9tIGBydW5DaGlsZGAuIERlZmF1bHRzIHRvIHNwYXduaW5nIGEgYEZsb3dDaGFydEV4ZWN1dG9yYC4gKi9cbiAgcmVhZG9ubHkgcnVuQ2hpbGQ/OiBDaGlsZFJ1bm5lcjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVNldFRpbWVvdXREcml2ZXIob3B0czogU2V0VGltZW91dERyaXZlck9wdGlvbnMgPSB7fSk6IERldGFjaERyaXZlciB7XG4gIGNvbnN0IGRlbGF5TXMgPSBvcHRzLmRlbGF5TXMgPz8gMDtcbiAgY29uc3QgcnVuQ2hpbGQgPSBvcHRzLnJ1bkNoaWxkID8/IGRlZmF1bHRSdW5DaGlsZDtcbiAgY29uc3QgcXVldWU6IFdvcmtJdGVtW10gPSBbXTtcbiAgbGV0IHNjaGVkdWxlZCA9IGZhbHNlO1xuXG4gIGZ1bmN0aW9uIGZsdXNoKCk6IHZvaWQge1xuICAgIHNjaGVkdWxlZCA9IGZhbHNlO1xuICAgIGNvbnN0IGl0ZW1zID0gcXVldWUuc3BsaWNlKDApO1xuICAgIGZvciAoY29uc3QgaXRlbSBvZiBpdGVtcykge1xuICAgICAgZXhlY3V0ZU9uZShpdGVtLCBydW5DaGlsZCkudGhlbih1bmRlZmluZWQsIHVuZGVmaW5lZCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiBkZWxheU1zID09PSAwID8gJ3NldC10aW1lb3V0JyA6IGBzZXQtdGltZW91dC0ke2RlbGF5TXN9bXNgLFxuICAgIGNhcGFiaWxpdGllczogeyBicm93c2VyU2FmZTogdHJ1ZSwgbm9kZVNhZmU6IHRydWUsIGVkZ2VTYWZlOiB0cnVlIH0sXG4gICAgc2NoZWR1bGUoY2hpbGQ6IEZsb3dDaGFydCwgaW5wdXQ6IHVua25vd24sIHJlZklkOiBzdHJpbmcpOiBEZXRhY2hIYW5kbGUge1xuICAgICAgY29uc3QgaGFuZGxlID0gY3JlYXRlSGFuZGxlKHJlZklkKTtcbiAgICAgIHJlZ2lzdGVyKGhhbmRsZSk7XG4gICAgICBxdWV1ZS5wdXNoKHsgY2hpbGQsIGlucHV0LCBoYW5kbGUgfSk7XG4gICAgICBpZiAoIXNjaGVkdWxlZCkge1xuICAgICAgICBzY2hlZHVsZWQgPSB0cnVlO1xuICAgICAgICBzZXRUaW1lb3V0KGZsdXNoLCBkZWxheU1zKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBoYW5kbGU7XG4gICAgfSxcbiAgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZXhlY3V0ZU9uZShpdGVtOiBXb3JrSXRlbSwgcnVuQ2hpbGQ6IENoaWxkUnVubmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IGltcGwgPSBhc0ltcGwoaXRlbS5oYW5kbGUpO1xuICBpbXBsLl9tYXJrUnVubmluZygpO1xuICB0cnkge1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHJ1bkNoaWxkKGl0ZW0uY2hpbGQsIGl0ZW0uaW5wdXQpO1xuICAgIGltcGwuX21hcmtEb25lKHJlc3VsdCk7XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGltcGwuX21hcmtGYWlsZWQoZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIgOiBuZXcgRXJyb3IoU3RyaW5nKGVycikpKTtcbiAgfSBmaW5hbGx5IHtcbiAgICB1bnJlZ2lzdGVyKGltcGwuaWQpO1xuICB9XG59XG5cbi8qKiBEZWZhdWx0IHNpbmdsZXRvbiDigJQgemVyby1kZWxheSAobmV4dCBtYWNyb3Rhc2spLiBGb3IgY29uZmlndXJhYmxlXG4gKiAgZGVsYXlzLCB1c2UgYGNyZWF0ZVNldFRpbWVvdXREcml2ZXIoeyBkZWxheU1zIH0pYC4gKi9cbmV4cG9ydCBjb25zdCBzZXRUaW1lb3V0RHJpdmVyOiBEZXRhY2hEcml2ZXIgPSBjcmVhdGVTZXRUaW1lb3V0RHJpdmVyKCk7XG4iXX0=
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* detach/drivers/workerThread.ts — Run detached work in a Node.js
|
|
4
|
+
* Worker Thread (or browser Web Worker).
|
|
5
|
+
*
|
|
6
|
+
* Pattern: Adapter — translates the consumer's child flowchart into
|
|
7
|
+
* a worker message + lifecycle handoff. The worker is owned
|
|
8
|
+
* by the driver instance; restarted on crash.
|
|
9
|
+
* Role: CPU-isolation driver — when detached work is genuinely
|
|
10
|
+
* expensive (heavy parsing, hashing, image processing) and
|
|
11
|
+
* you don't want it blocking the main thread's event loop
|
|
12
|
+
* even for a microtask burst.
|
|
13
|
+
*
|
|
14
|
+
* Caveats / IMPORTANT v1 limitations:
|
|
15
|
+
* - The worker entry point is a CONSUMER-PROVIDED file path / URL —
|
|
16
|
+
* this driver does NOT auto-spawn FlowChartExecutor in a worker.
|
|
17
|
+
* Workers can't `import('footprintjs')` portably without setup,
|
|
18
|
+
* and the worker file's lifecycle differs by runtime
|
|
19
|
+
* (Node Worker vs Web Worker vs Bun). Consumer writes the worker
|
|
20
|
+
* code; this driver just hands them a uniform `(input, handle)`
|
|
21
|
+
* API.
|
|
22
|
+
* - The "child flowchart" parameter is IGNORED in v1 (we only ship
|
|
23
|
+
* the input). The chart shape doesn't survive structuredClone +
|
|
24
|
+
* postMessage anyway. v2 may add a serialization protocol.
|
|
25
|
+
*
|
|
26
|
+
* Two ways to consume:
|
|
27
|
+
*
|
|
28
|
+
* 1. Node.js: pass a file path
|
|
29
|
+
* `createWorkerThreadDriver({ workerScript: '/path/to/worker.js' })`
|
|
30
|
+
*
|
|
31
|
+
* 2. Browser: pass a URL or pre-built Worker instance
|
|
32
|
+
* `createWorkerThreadDriver({ worker: new Worker(url) })`
|
|
33
|
+
*/
|
|
34
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
|
+
exports.createWorkerThreadDriver = void 0;
|
|
36
|
+
const handle_js_1 = require("../handle.js");
|
|
37
|
+
const registry_js_1 = require("../registry.js");
|
|
38
|
+
let nextMessageId = 0;
|
|
39
|
+
function createWorkerThreadDriver(opts) {
|
|
40
|
+
let worker;
|
|
41
|
+
const inFlight = new Map();
|
|
42
|
+
// If consumer provided a Worker at construction time, bind its
|
|
43
|
+
// 'message' handler eagerly so replies are routed back to handles.
|
|
44
|
+
// Lazy construction (via `workerScript`) defers binding to first use.
|
|
45
|
+
if (opts.worker) {
|
|
46
|
+
worker = opts.worker;
|
|
47
|
+
bindWorker(worker, inFlight);
|
|
48
|
+
}
|
|
49
|
+
function ensureWorker() {
|
|
50
|
+
if (worker)
|
|
51
|
+
return worker;
|
|
52
|
+
if (!opts.workerScript) {
|
|
53
|
+
throw new Error('[detach] workerThreadDriver: provide either `worker` (a constructed Worker) ' +
|
|
54
|
+
'or `workerScript` (a path/URL) at driver creation.');
|
|
55
|
+
}
|
|
56
|
+
// Lazy-import Node's worker_threads — keeps browser bundles clean.
|
|
57
|
+
if (typeof require !== 'function') {
|
|
58
|
+
throw new Error('[detach] workerThreadDriver: `workerScript` requires Node.js (CommonJS `require`).');
|
|
59
|
+
}
|
|
60
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
61
|
+
const { Worker } = require('worker_threads');
|
|
62
|
+
worker = new Worker(opts.workerScript);
|
|
63
|
+
bindWorker(worker, inFlight);
|
|
64
|
+
return worker;
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
name: 'worker-thread',
|
|
68
|
+
capabilities: { nodeSafe: true, cpuIsolated: true },
|
|
69
|
+
validate() {
|
|
70
|
+
if (!opts.worker && !opts.workerScript) {
|
|
71
|
+
throw new Error('[detach] workerThreadDriver requires either a pre-built `worker` or a `workerScript` path.');
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
schedule(_child, input, refId) {
|
|
75
|
+
const handle = (0, handle_js_1.createHandle)(refId);
|
|
76
|
+
(0, registry_js_1.register)(handle);
|
|
77
|
+
const impl = (0, handle_js_1.asImpl)(handle);
|
|
78
|
+
impl._markRunning();
|
|
79
|
+
const messageId = nextMessageId++;
|
|
80
|
+
inFlight.set(messageId, { handle });
|
|
81
|
+
try {
|
|
82
|
+
const w = ensureWorker();
|
|
83
|
+
w.postMessage({ messageId, refId, input });
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
impl._markFailed(err instanceof Error ? err : new Error(String(err)));
|
|
87
|
+
(0, registry_js_1.unregister)(impl.id);
|
|
88
|
+
inFlight.delete(messageId);
|
|
89
|
+
}
|
|
90
|
+
return handle;
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
exports.createWorkerThreadDriver = createWorkerThreadDriver;
|
|
95
|
+
function bindWorker(worker, inFlight) {
|
|
96
|
+
const handler = (msg) => {
|
|
97
|
+
const m = msg;
|
|
98
|
+
if (!m || typeof m.messageId !== 'number')
|
|
99
|
+
return;
|
|
100
|
+
const slot = inFlight.get(m.messageId);
|
|
101
|
+
if (!slot)
|
|
102
|
+
return;
|
|
103
|
+
inFlight.delete(m.messageId);
|
|
104
|
+
const impl = (0, handle_js_1.asImpl)(slot.handle);
|
|
105
|
+
if (m.ok) {
|
|
106
|
+
impl._markDone(m.result);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
impl._markFailed(new Error(m.error ?? 'worker reported failure'));
|
|
110
|
+
}
|
|
111
|
+
(0, registry_js_1.unregister)(impl.id);
|
|
112
|
+
};
|
|
113
|
+
// Node Worker (worker_threads): EventEmitter-shape (`on('message', ...)`).
|
|
114
|
+
if (typeof worker.on === 'function')
|
|
115
|
+
worker.on('message', handler);
|
|
116
|
+
// Browser Worker / Web Worker: EventTarget-shape (`addEventListener`).
|
|
117
|
+
else if (typeof worker.addEventListener === 'function') {
|
|
118
|
+
worker.addEventListener('message', (evt) => handler(evt?.data));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid29ya2VyVGhyZWFkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9kZXRhY2gvZHJpdmVycy93b3JrZXJUaHJlYWQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBK0JHOzs7QUFHSCw0Q0FBb0Q7QUFDcEQsZ0RBQXNEO0FBNkJ0RCxJQUFJLGFBQWEsR0FBRyxDQUFDLENBQUM7QUFFdEIsU0FBZ0Isd0JBQXdCLENBQUMsSUFBK0I7SUFDdEUsSUFBSSxNQUE4QixDQUFDO0lBQ25DLE1BQU0sUUFBUSxHQUFHLElBQUksR0FBRyxFQUFvQixDQUFDO0lBRTdDLCtEQUErRDtJQUMvRCxtRUFBbUU7SUFDbkUsc0VBQXNFO0lBQ3RFLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ2hCLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO1FBQ3JCLFVBQVUsQ0FBQyxNQUFNLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDL0IsQ0FBQztJQUVELFNBQVMsWUFBWTtRQUNuQixJQUFJLE1BQU07WUFBRSxPQUFPLE1BQU0sQ0FBQztRQUMxQixJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ3ZCLE1BQU0sSUFBSSxLQUFLLENBQ2IsOEVBQThFO2dCQUM1RSxvREFBb0QsQ0FDdkQsQ0FBQztRQUNKLENBQUM7UUFDRCxtRUFBbUU7UUFDbkUsSUFBSSxPQUFPLE9BQU8sS0FBSyxVQUFVLEVBQUUsQ0FBQztZQUNsQyxNQUFNLElBQUksS0FBSyxDQUFDLG9GQUFvRixDQUFDLENBQUM7UUFDeEcsQ0FBQztRQUNELGlFQUFpRTtRQUNqRSxNQUFNLEVBQUUsTUFBTSxFQUFFLEdBQUcsT0FBTyxDQUFDLGdCQUFnQixDQUE4QyxDQUFDO1FBQzFGLE1BQU0sR0FBRyxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDdkMsVUFBVSxDQUFDLE1BQU0sRUFBRSxRQUFRLENBQUMsQ0FBQztRQUM3QixPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO0lBRUQsT0FBTztRQUNMLElBQUksRUFBRSxlQUFlO1FBQ3JCLFlBQVksRUFBRSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRTtRQUNuRCxRQUFRO1lBQ04sSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7Z0JBQ3ZDLE1BQU0sSUFBSSxLQUFLLENBQUMsNEZBQTRGLENBQUMsQ0FBQztZQUNoSCxDQUFDO1FBQ0gsQ0FBQztRQUNELFFBQVEsQ0FBQyxNQUFpQixFQUFFLEtBQWMsRUFBRSxLQUFhO1lBQ3ZELE1BQU0sTUFBTSxHQUFHLElBQUEsd0JBQVksRUFBQyxLQUFLLENBQUMsQ0FBQztZQUNuQyxJQUFBLHNCQUFRLEVBQUMsTUFBTSxDQUFDLENBQUM7WUFDakIsTUFBTSxJQUFJLEdBQUcsSUFBQSxrQkFBTSxFQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUVwQixNQUFNLFNBQVMsR0FBRyxhQUFhLEVBQUUsQ0FBQztZQUNsQyxRQUFRLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUM7WUFFcEMsSUFBSSxDQUFDO2dCQUNILE1BQU0sQ0FBQyxHQUFHLFlBQVksRUFBRSxDQUFDO2dCQUN6QixDQUFDLENBQUMsV0FBVyxDQUFDLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1lBQzdDLENBQUM7WUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO2dCQUNiLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUN0RSxJQUFBLHdCQUFVLEVBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUNwQixRQUFRLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQzdCLENBQUM7WUFFRCxPQUFPLE1BQU0sQ0FBQztRQUNoQixDQUFDO0tBQ0YsQ0FBQztBQUNKLENBQUM7QUE1REQsNERBNERDO0FBRUQsU0FBUyxVQUFVLENBQUMsTUFBa0IsRUFBRSxRQUErQjtJQUNyRSxNQUFNLE9BQU8sR0FBRyxDQUFDLEdBQVksRUFBUSxFQUFFO1FBQ3JDLE1BQU0sQ0FBQyxHQUFHLEdBQXlGLENBQUM7UUFDcEcsSUFBSSxDQUFDLENBQUMsSUFBSSxPQUFPLENBQUMsQ0FBQyxTQUFTLEtBQUssUUFBUTtZQUFFLE9BQU87UUFDbEQsTUFBTSxJQUFJLEdBQUcsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDdkMsSUFBSSxDQUFDLElBQUk7WUFBRSxPQUFPO1FBQ2xCLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBRTdCLE1BQU0sSUFBSSxHQUFHLElBQUEsa0JBQU0sRUFBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDakMsSUFBSSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDVCxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUMzQixDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSx5QkFBeUIsQ0FBQyxDQUFDLENBQUM7UUFDcEUsQ0FBQztRQUNELElBQUEsd0JBQVUsRUFBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDdEIsQ0FBQyxDQUFDO0lBRUYsMkVBQTJFO0lBQzNFLElBQUksT0FBTyxNQUFNLENBQUMsRUFBRSxLQUFLLFVBQVU7UUFBRSxNQUFNLENBQUMsRUFBRSxDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUNuRSx1RUFBdUU7U0FDbEUsSUFBSSxPQUFPLE1BQU0sQ0FBQyxnQkFBZ0IsS0FBSyxVQUFVLEVBQUUsQ0FBQztRQUN2RCxNQUFNLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxFQUFFLENBQUMsR0FBWSxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUUsR0FBMEIsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ25HLENBQUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBkZXRhY2gvZHJpdmVycy93b3JrZXJUaHJlYWQudHMg4oCUIFJ1biBkZXRhY2hlZCB3b3JrIGluIGEgTm9kZS5qc1xuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgV29ya2VyIFRocmVhZCAob3IgYnJvd3NlciBXZWIgV29ya2VyKS5cbiAqXG4gKiBQYXR0ZXJuOiAgQWRhcHRlciDigJQgdHJhbnNsYXRlcyB0aGUgY29uc3VtZXIncyBjaGlsZCBmbG93Y2hhcnQgaW50b1xuICogICAgICAgICAgIGEgd29ya2VyIG1lc3NhZ2UgKyBsaWZlY3ljbGUgaGFuZG9mZi4gVGhlIHdvcmtlciBpcyBvd25lZFxuICogICAgICAgICAgIGJ5IHRoZSBkcml2ZXIgaW5zdGFuY2U7IHJlc3RhcnRlZCBvbiBjcmFzaC5cbiAqIFJvbGU6ICAgICBDUFUtaXNvbGF0aW9uIGRyaXZlciDigJQgd2hlbiBkZXRhY2hlZCB3b3JrIGlzIGdlbnVpbmVseVxuICogICAgICAgICAgIGV4cGVuc2l2ZSAoaGVhdnkgcGFyc2luZywgaGFzaGluZywgaW1hZ2UgcHJvY2Vzc2luZykgYW5kXG4gKiAgICAgICAgICAgeW91IGRvbid0IHdhbnQgaXQgYmxvY2tpbmcgdGhlIG1haW4gdGhyZWFkJ3MgZXZlbnQgbG9vcFxuICogICAgICAgICAgIGV2ZW4gZm9yIGEgbWljcm90YXNrIGJ1cnN0LlxuICpcbiAqIENhdmVhdHMgLyBJTVBPUlRBTlQgdjEgbGltaXRhdGlvbnM6XG4gKiAgIC0gVGhlIHdvcmtlciBlbnRyeSBwb2ludCBpcyBhIENPTlNVTUVSLVBST1ZJREVEIGZpbGUgcGF0aCAvIFVSTCDigJRcbiAqICAgICB0aGlzIGRyaXZlciBkb2VzIE5PVCBhdXRvLXNwYXduIEZsb3dDaGFydEV4ZWN1dG9yIGluIGEgd29ya2VyLlxuICogICAgIFdvcmtlcnMgY2FuJ3QgYGltcG9ydCgnZm9vdHByaW50anMnKWAgcG9ydGFibHkgd2l0aG91dCBzZXR1cCxcbiAqICAgICBhbmQgdGhlIHdvcmtlciBmaWxlJ3MgbGlmZWN5Y2xlIGRpZmZlcnMgYnkgcnVudGltZVxuICogICAgIChOb2RlIFdvcmtlciB2cyBXZWIgV29ya2VyIHZzIEJ1bikuIENvbnN1bWVyIHdyaXRlcyB0aGUgd29ya2VyXG4gKiAgICAgY29kZTsgdGhpcyBkcml2ZXIganVzdCBoYW5kcyB0aGVtIGEgdW5pZm9ybSBgKGlucHV0LCBoYW5kbGUpYFxuICogICAgIEFQSS5cbiAqICAgLSBUaGUgXCJjaGlsZCBmbG93Y2hhcnRcIiBwYXJhbWV0ZXIgaXMgSUdOT1JFRCBpbiB2MSAod2Ugb25seSBzaGlwXG4gKiAgICAgdGhlIGlucHV0KS4gVGhlIGNoYXJ0IHNoYXBlIGRvZXNuJ3Qgc3Vydml2ZSBzdHJ1Y3R1cmVkQ2xvbmUgK1xuICogICAgIHBvc3RNZXNzYWdlIGFueXdheS4gdjIgbWF5IGFkZCBhIHNlcmlhbGl6YXRpb24gcHJvdG9jb2wuXG4gKlxuICogVHdvIHdheXMgdG8gY29uc3VtZTpcbiAqXG4gKiAgIDEuIE5vZGUuanM6IHBhc3MgYSBmaWxlIHBhdGhcbiAqICAgICAgYGNyZWF0ZVdvcmtlclRocmVhZERyaXZlcih7IHdvcmtlclNjcmlwdDogJy9wYXRoL3RvL3dvcmtlci5qcycgfSlgXG4gKlxuICogICAyLiBCcm93c2VyOiBwYXNzIGEgVVJMIG9yIHByZS1idWlsdCBXb3JrZXIgaW5zdGFuY2VcbiAqICAgICAgYGNyZWF0ZVdvcmtlclRocmVhZERyaXZlcih7IHdvcmtlcjogbmV3IFdvcmtlcih1cmwpIH0pYFxuICovXG5cbmltcG9ydCB0eXBlIHsgRmxvd0NoYXJ0IH0gZnJvbSAnLi4vLi4vYnVpbGRlci90eXBlcy5qcyc7XG5pbXBvcnQgeyBhc0ltcGwsIGNyZWF0ZUhhbmRsZSB9IGZyb20gJy4uL2hhbmRsZS5qcyc7XG5pbXBvcnQgeyByZWdpc3RlciwgdW5yZWdpc3RlciB9IGZyb20gJy4uL3JlZ2lzdHJ5LmpzJztcbmltcG9ydCB0eXBlIHsgRGV0YWNoRHJpdmVyLCBEZXRhY2hIYW5kbGUgfSBmcm9tICcuLi90eXBlcy5qcyc7XG5cbi8vIE5vZGUtb25seSBDb21tb25KUyBgcmVxdWlyZWAuIFdlIGRvbid0IHNoaXAgQHR5cGVzL25vZGUsIHNvIGRlY2xhcmVcbi8vIHRoZSBtaW5pbWFsIHNoYXBlIGhlcmUuIFVzZWQgb25seSBpbiB0aGUgbGF6eSBgd29ya2VyU2NyaXB0YCBwYXRoO1xuLy8gYnJvd3NlciBjb25zdW1lcnMgcGFzcyBhIHByZS1jb25zdHJ1Y3RlZCBgV29ya2VyYCBhbmQgbmV2ZXIgaGl0IGl0LlxuZGVjbGFyZSBjb25zdCByZXF1aXJlOiAoKG1vZDogc3RyaW5nKSA9PiB1bmtub3duKSB8IHVuZGVmaW5lZDtcblxuaW50ZXJmYWNlIFdvcmtlckxpa2Uge1xuICBwb3N0TWVzc2FnZShtZXNzYWdlOiB1bmtub3duLCB0cmFuc2Zlcj86IFRyYW5zZmVyYWJsZVtdKTogdm9pZDtcbiAgdGVybWluYXRlPygpOiB1bmtub3duO1xuICBvbj8oZXZlbnQ6IHN0cmluZywgbGlzdGVuZXI6IChtc2c6IHVua25vd24pID0+IHZvaWQpOiB2b2lkO1xuICBhZGRFdmVudExpc3RlbmVyPyhldmVudDogc3RyaW5nLCBsaXN0ZW5lcjogKG1zZzogdW5rbm93bikgPT4gdm9pZCk6IHZvaWQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgV29ya2VyVGhyZWFkRHJpdmVyT3B0aW9ucyB7XG4gIC8qKiBQcmUtY29uc3RydWN0ZWQgV29ya2VyIGluc3RhbmNlLiBQYXNzIGVpdGhlciB0aGlzIE9SXG4gICAqICBgd29ya2VyU2NyaXB0YCDigJQgbm90IGJvdGguICovXG4gIHJlYWRvbmx5IHdvcmtlcj86IFdvcmtlckxpa2U7XG4gIC8qKiBQYXRoIC8gVVJMIHRvIHRoZSB3b3JrZXIgc2NyaXB0LiBVc2VkIG9ubHkgd2hlbiBgd29ya2VyYCBpc1xuICAgKiAgbm90IHByb3ZpZGVkOyB0aGUgZHJpdmVyIGNvbnN0cnVjdHMgYSBXb3JrZXIgZnJvbSB0aGlzIG9uIGRlbWFuZFxuICAgKiAgKE5vZGUgYHdvcmtlcl90aHJlYWRzYCBBUEkpLiAqL1xuICByZWFkb25seSB3b3JrZXJTY3JpcHQ/OiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBJbkZsaWdodCB7XG4gIHJlYWRvbmx5IGhhbmRsZTogRGV0YWNoSGFuZGxlO1xufVxuXG5sZXQgbmV4dE1lc3NhZ2VJZCA9IDA7XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVXb3JrZXJUaHJlYWREcml2ZXIob3B0czogV29ya2VyVGhyZWFkRHJpdmVyT3B0aW9ucyk6IERldGFjaERyaXZlciB7XG4gIGxldCB3b3JrZXI6IFdvcmtlckxpa2UgfCB1bmRlZmluZWQ7XG4gIGNvbnN0IGluRmxpZ2h0ID0gbmV3IE1hcDxudW1iZXIsIEluRmxpZ2h0PigpO1xuXG4gIC8vIElmIGNvbnN1bWVyIHByb3ZpZGVkIGEgV29ya2VyIGF0IGNvbnN0cnVjdGlvbiB0aW1lLCBiaW5kIGl0c1xuICAvLyAnbWVzc2FnZScgaGFuZGxlciBlYWdlcmx5IHNvIHJlcGxpZXMgYXJlIHJvdXRlZCBiYWNrIHRvIGhhbmRsZXMuXG4gIC8vIExhenkgY29uc3RydWN0aW9uICh2aWEgYHdvcmtlclNjcmlwdGApIGRlZmVycyBiaW5kaW5nIHRvIGZpcnN0IHVzZS5cbiAgaWYgKG9wdHMud29ya2VyKSB7XG4gICAgd29ya2VyID0gb3B0cy53b3JrZXI7XG4gICAgYmluZFdvcmtlcih3b3JrZXIsIGluRmxpZ2h0KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGVuc3VyZVdvcmtlcigpOiBXb3JrZXJMaWtlIHtcbiAgICBpZiAod29ya2VyKSByZXR1cm4gd29ya2VyO1xuICAgIGlmICghb3B0cy53b3JrZXJTY3JpcHQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgJ1tkZXRhY2hdIHdvcmtlclRocmVhZERyaXZlcjogcHJvdmlkZSBlaXRoZXIgYHdvcmtlcmAgKGEgY29uc3RydWN0ZWQgV29ya2VyKSAnICtcbiAgICAgICAgICAnb3IgYHdvcmtlclNjcmlwdGAgKGEgcGF0aC9VUkwpIGF0IGRyaXZlciBjcmVhdGlvbi4nLFxuICAgICAgKTtcbiAgICB9XG4gICAgLy8gTGF6eS1pbXBvcnQgTm9kZSdzIHdvcmtlcl90aHJlYWRzIOKAlCBrZWVwcyBicm93c2VyIGJ1bmRsZXMgY2xlYW4uXG4gICAgaWYgKHR5cGVvZiByZXF1aXJlICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1tkZXRhY2hdIHdvcmtlclRocmVhZERyaXZlcjogYHdvcmtlclNjcmlwdGAgcmVxdWlyZXMgTm9kZS5qcyAoQ29tbW9uSlMgYHJlcXVpcmVgKS4nKTtcbiAgICB9XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgICBjb25zdCB7IFdvcmtlciB9ID0gcmVxdWlyZSgnd29ya2VyX3RocmVhZHMnKSBhcyB7IFdvcmtlcjogbmV3IChzOiBzdHJpbmcpID0+IFdvcmtlckxpa2UgfTtcbiAgICB3b3JrZXIgPSBuZXcgV29ya2VyKG9wdHMud29ya2VyU2NyaXB0KTtcbiAgICBiaW5kV29ya2VyKHdvcmtlciwgaW5GbGlnaHQpO1xuICAgIHJldHVybiB3b3JrZXI7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIG5hbWU6ICd3b3JrZXItdGhyZWFkJyxcbiAgICBjYXBhYmlsaXRpZXM6IHsgbm9kZVNhZmU6IHRydWUsIGNwdUlzb2xhdGVkOiB0cnVlIH0sXG4gICAgdmFsaWRhdGUoKTogdm9pZCB7XG4gICAgICBpZiAoIW9wdHMud29ya2VyICYmICFvcHRzLndvcmtlclNjcmlwdCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1tkZXRhY2hdIHdvcmtlclRocmVhZERyaXZlciByZXF1aXJlcyBlaXRoZXIgYSBwcmUtYnVpbHQgYHdvcmtlcmAgb3IgYSBgd29ya2VyU2NyaXB0YCBwYXRoLicpO1xuICAgICAgfVxuICAgIH0sXG4gICAgc2NoZWR1bGUoX2NoaWxkOiBGbG93Q2hhcnQsIGlucHV0OiB1bmtub3duLCByZWZJZDogc3RyaW5nKTogRGV0YWNoSGFuZGxlIHtcbiAgICAgIGNvbnN0IGhhbmRsZSA9IGNyZWF0ZUhhbmRsZShyZWZJZCk7XG4gICAgICByZWdpc3RlcihoYW5kbGUpO1xuICAgICAgY29uc3QgaW1wbCA9IGFzSW1wbChoYW5kbGUpO1xuICAgICAgaW1wbC5fbWFya1J1bm5pbmcoKTtcblxuICAgICAgY29uc3QgbWVzc2FnZUlkID0gbmV4dE1lc3NhZ2VJZCsrO1xuICAgICAgaW5GbGlnaHQuc2V0KG1lc3NhZ2VJZCwgeyBoYW5kbGUgfSk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHcgPSBlbnN1cmVXb3JrZXIoKTtcbiAgICAgICAgdy5wb3N0TWVzc2FnZSh7IG1lc3NhZ2VJZCwgcmVmSWQsIGlucHV0IH0pO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGltcGwuX21hcmtGYWlsZWQoZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIgOiBuZXcgRXJyb3IoU3RyaW5nKGVycikpKTtcbiAgICAgICAgdW5yZWdpc3RlcihpbXBsLmlkKTtcbiAgICAgICAgaW5GbGlnaHQuZGVsZXRlKG1lc3NhZ2VJZCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBoYW5kbGU7XG4gICAgfSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gYmluZFdvcmtlcih3b3JrZXI6IFdvcmtlckxpa2UsIGluRmxpZ2h0OiBNYXA8bnVtYmVyLCBJbkZsaWdodD4pOiB2b2lkIHtcbiAgY29uc3QgaGFuZGxlciA9IChtc2c6IHVua25vd24pOiB2b2lkID0+IHtcbiAgICBjb25zdCBtID0gbXNnIGFzIHsgbWVzc2FnZUlkPzogbnVtYmVyOyBvaz86IGJvb2xlYW47IHJlc3VsdD86IHVua25vd247IGVycm9yPzogc3RyaW5nIH0gfCB1bmRlZmluZWQ7XG4gICAgaWYgKCFtIHx8IHR5cGVvZiBtLm1lc3NhZ2VJZCAhPT0gJ251bWJlcicpIHJldHVybjtcbiAgICBjb25zdCBzbG90ID0gaW5GbGlnaHQuZ2V0KG0ubWVzc2FnZUlkKTtcbiAgICBpZiAoIXNsb3QpIHJldHVybjtcbiAgICBpbkZsaWdodC5kZWxldGUobS5tZXNzYWdlSWQpO1xuXG4gICAgY29uc3QgaW1wbCA9IGFzSW1wbChzbG90LmhhbmRsZSk7XG4gICAgaWYgKG0ub2spIHtcbiAgICAgIGltcGwuX21hcmtEb25lKG0ucmVzdWx0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgaW1wbC5fbWFya0ZhaWxlZChuZXcgRXJyb3IobS5lcnJvciA/PyAnd29ya2VyIHJlcG9ydGVkIGZhaWx1cmUnKSk7XG4gICAgfVxuICAgIHVucmVnaXN0ZXIoaW1wbC5pZCk7XG4gIH07XG5cbiAgLy8gTm9kZSBXb3JrZXIgKHdvcmtlcl90aHJlYWRzKTogRXZlbnRFbWl0dGVyLXNoYXBlIChgb24oJ21lc3NhZ2UnLCAuLi4pYCkuXG4gIGlmICh0eXBlb2Ygd29ya2VyLm9uID09PSAnZnVuY3Rpb24nKSB3b3JrZXIub24oJ21lc3NhZ2UnLCBoYW5kbGVyKTtcbiAgLy8gQnJvd3NlciBXb3JrZXIgLyBXZWIgV29ya2VyOiBFdmVudFRhcmdldC1zaGFwZSAoYGFkZEV2ZW50TGlzdGVuZXJgKS5cbiAgZWxzZSBpZiAodHlwZW9mIHdvcmtlci5hZGRFdmVudExpc3RlbmVyID09PSAnZnVuY3Rpb24nKSB7XG4gICAgd29ya2VyLmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCAoZXZ0OiB1bmtub3duKSA9PiBoYW5kbGVyKChldnQgYXMgeyBkYXRhPzogdW5rbm93biB9KT8uZGF0YSkpO1xuICB9XG59XG4iXX0=
|