footprintjs 9.41.0 → 9.43.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 +7 -3
- package/CLAUDE.md +12 -11
- package/README.md +7 -3
- package/dist/advanced.js +4 -3
- package/dist/esm/advanced.d.ts +3 -1
- package/dist/esm/advanced.js +3 -2
- package/dist/esm/index.d.ts +3 -3
- package/dist/esm/index.js +1 -1
- package/dist/esm/lib/builder/FlowChartBuilder.d.ts +14 -4
- package/dist/esm/lib/builder/FlowChartBuilder.js +25 -7
- package/dist/esm/lib/builder/types.d.ts +2 -3
- package/dist/esm/lib/builder/types.js +1 -1
- package/dist/esm/lib/capture/freeze.d.ts +5 -5
- package/dist/esm/lib/capture/freeze.js +5 -4
- package/dist/esm/lib/contract/index.d.ts +5 -8
- package/dist/esm/lib/contract/index.js +5 -10
- package/dist/esm/lib/contract/types.d.ts +3 -81
- package/dist/esm/lib/contract/types.js +4 -5
- package/dist/esm/lib/decide/decide.js +13 -46
- package/dist/esm/lib/detach/drivers/batch.d.ts +9 -0
- package/dist/esm/lib/detach/drivers/batch.js +79 -0
- package/dist/esm/lib/detach/drivers/microtaskBatch.d.ts +17 -20
- package/dist/esm/lib/detach/drivers/microtaskBatch.js +20 -72
- package/dist/esm/lib/detach/drivers/setImmediate.js +10 -41
- package/dist/esm/lib/detach/drivers/setTimeout.js +3 -36
- package/dist/esm/lib/detach/types.d.ts +17 -20
- package/dist/esm/lib/detach/types.js +9 -11
- package/dist/esm/lib/engine/handlers/ChildrenExecutor.js +7 -3
- package/dist/esm/lib/engine/handlers/DeciderHandler.js +7 -5
- package/dist/esm/lib/engine/handlers/ParallelForEachHandler.d.ts +2 -3
- package/dist/esm/lib/engine/handlers/ParallelForEachHandler.js +21 -24
- package/dist/esm/lib/engine/handlers/SelectorHandler.d.ts +2 -4
- package/dist/esm/lib/engine/handlers/SelectorHandler.js +15 -7
- package/dist/esm/lib/engine/handlers/StageRunner.js +11 -22
- package/dist/esm/lib/engine/handlers/SubflowExecutor.js +32 -17
- package/dist/esm/lib/engine/handlers/SubflowInputMapper.d.ts +4 -3
- package/dist/esm/lib/engine/handlers/SubflowInputMapper.js +19 -8
- package/dist/esm/lib/engine/handlers/breakFlag.d.ts +3 -0
- package/dist/esm/lib/engine/handlers/breakFlag.js +9 -0
- package/dist/esm/lib/engine/handlers/commitStage.js +3 -3
- package/dist/esm/lib/engine/handlers/servedPause.d.ts +15 -0
- package/dist/esm/lib/engine/handlers/servedPause.js +26 -0
- package/dist/esm/lib/engine/handlers/stageError.d.ts +20 -0
- package/dist/esm/lib/engine/handlers/stageError.js +28 -0
- package/dist/esm/lib/engine/narrative/CombinedNarrativeRecorder.d.ts +6 -1
- package/dist/esm/lib/engine/narrative/CombinedNarrativeRecorder.js +40 -67
- package/dist/esm/lib/engine/narrative/FlowRecorderDispatcher.d.ts +3 -3
- package/dist/esm/lib/engine/narrative/FlowRecorderDispatcher.js +4 -8
- package/dist/esm/lib/engine/narrative/NarrativeFlowRecorder.d.ts +7 -1
- package/dist/esm/lib/engine/narrative/NarrativeFlowRecorder.js +28 -48
- package/dist/esm/lib/engine/narrative/formatting/resolveText.d.ts +6 -0
- package/dist/esm/lib/engine/narrative/formatting/resolveText.js +9 -0
- package/dist/esm/lib/engine/narrative/formatting/sentences.d.ts +16 -0
- package/dist/esm/lib/engine/narrative/formatting/sentences.js +50 -0
- package/dist/esm/lib/engine/narrative/narrativeTypes.d.ts +2 -0
- package/dist/esm/lib/engine/narrative/narrativeTypes.js +1 -1
- package/dist/esm/lib/engine/narrative/recorders/RLENarrativeFlowRecorder.js +3 -7
- package/dist/esm/lib/engine/narrative/recorders/SeparateNarrativeFlowRecorder.js +3 -7
- package/dist/esm/lib/engine/narrative/recorders/WindowedNarrativeFlowRecorder.d.ts +0 -1
- package/dist/esm/lib/engine/narrative/recorders/WindowedNarrativeFlowRecorder.js +5 -10
- package/dist/esm/lib/engine/narrative/types.d.ts +18 -8
- package/dist/esm/lib/engine/narrative/types.js +1 -1
- package/dist/esm/lib/engine/traversal/FlowchartTraverser.d.ts +8 -3
- package/dist/esm/lib/engine/traversal/FlowchartTraverser.js +64 -33
- package/dist/esm/lib/engine/types.d.ts +4 -0
- package/dist/esm/lib/engine/types.js +1 -1
- package/dist/esm/lib/memory/DiagnosticCollector.d.ts +12 -0
- package/dist/esm/lib/memory/DiagnosticCollector.js +53 -9
- package/dist/esm/lib/memory/EventLog.d.ts +9 -0
- package/dist/esm/lib/memory/EventLog.js +24 -1
- package/dist/esm/lib/memory/StageContext.d.ts +22 -1
- package/dist/esm/lib/memory/StageContext.js +61 -7
- package/dist/esm/lib/memory/eventPosition.d.ts +18 -0
- package/dist/esm/lib/memory/eventPosition.js +2 -0
- package/dist/esm/lib/memory/merge.d.ts +2 -1
- package/dist/esm/lib/memory/merge.js +15 -4
- package/dist/esm/lib/memory/redaction.d.ts +339 -17
- package/dist/esm/lib/memory/redaction.js +993 -32
- package/dist/esm/lib/observer-queue/deferredDispatcher.d.ts +2 -2
- package/dist/esm/lib/observer-queue/deferredDispatcher.js +3 -3
- package/dist/esm/lib/observer-queue/index.d.ts +7 -4
- package/dist/esm/lib/observer-queue/index.js +8 -5
- package/dist/esm/lib/pause/index.d.ts +1 -1
- package/dist/esm/lib/pause/index.js +1 -1
- package/dist/esm/lib/pause/record.js +19 -1
- package/dist/esm/lib/pause/types.d.ts +20 -0
- package/dist/esm/lib/pause/types.js +1 -1
- package/dist/esm/lib/reactive/createTypedScope.js +20 -21
- package/dist/esm/lib/reactive/index.d.ts +1 -1
- package/dist/esm/lib/reactive/index.js +2 -2
- package/dist/esm/lib/reactive/types.d.ts +0 -3
- package/dist/esm/lib/reactive/types.js +1 -23
- package/dist/esm/lib/recorder/EmitRecorder.d.ts +9 -0
- package/dist/esm/lib/recorder/EmitRecorder.js +1 -1
- package/dist/esm/lib/recorder/InOutRecorder.d.ts +5 -2
- package/dist/esm/lib/recorder/InOutRecorder.js +6 -3
- package/dist/esm/lib/runner/DeferredObserverTier.d.ts +4 -3
- package/dist/esm/lib/runner/DeferredObserverTier.js +5 -4
- package/dist/esm/lib/runner/ExecutionRuntime.d.ts +3 -0
- package/dist/esm/lib/runner/ExecutionRuntime.js +2 -1
- package/dist/esm/lib/runner/FlowChartExecutor.d.ts +11 -9
- package/dist/esm/lib/runner/FlowChartExecutor.js +18 -10
- package/dist/esm/lib/runner/attach.d.ts +3 -1
- package/dist/esm/lib/runner/attach.js +21 -31
- package/dist/esm/lib/runner/checkpoint.d.ts +3 -1
- package/dist/esm/lib/runner/checkpoint.js +4 -1
- package/dist/esm/lib/scope/ScopeFacade.d.ts +13 -1
- package/dist/esm/lib/scope/ScopeFacade.js +60 -39
- package/dist/esm/lib/scope/protection/createProtectedScope.js +5 -2
- package/dist/esm/lib/scope/protection/readonlyInput.d.ts +16 -6
- package/dist/esm/lib/scope/protection/readonlyInput.js +72 -9
- package/dist/esm/lib/scope/providers/baseStateCompatible.d.ts +10 -24
- package/dist/esm/lib/scope/providers/baseStateCompatible.js +35 -35
- package/dist/esm/lib/scope/providers/providers.d.ts +2 -2
- package/dist/esm/lib/scope/providers/providers.js +3 -3
- package/dist/esm/lib/scope/providers/resolve.js +2 -2
- package/dist/esm/lib/scope/providers/types.d.ts +4 -2
- package/dist/esm/lib/scope/providers/types.js +1 -1
- package/dist/esm/lib/scope/recorders/MetricRecorder.d.ts +2 -3
- package/dist/esm/lib/scope/recorders/MetricRecorder.js +11 -14
- package/dist/esm/lib/scope/runtime.d.ts +48 -0
- package/dist/esm/lib/scope/runtime.js +60 -0
- package/dist/esm/lib/scope/state/zod/defineScopeFromZod.d.ts +2 -2
- package/dist/esm/lib/scope/state/zod/defineScopeFromZod.js +17 -6
- package/dist/esm/lib/scope/state/zod/resolver.js +3 -15
- package/dist/esm/lib/scope/state/zod/scopeFactory.d.ts +7 -3
- package/dist/esm/lib/scope/state/zod/scopeFactory.js +57 -22
- package/dist/esm/lib/scope/state/zod/utils/validateHelper.d.ts +27 -18
- package/dist/esm/lib/scope/state/zod/utils/validateHelper.js +66 -67
- package/dist/esm/recorders.d.ts +3 -0
- package/dist/esm/recorders.js +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/builder/FlowChartBuilder.js +25 -7
- package/dist/lib/builder/types.js +1 -1
- package/dist/lib/capture/freeze.js +5 -4
- package/dist/lib/contract/index.js +6 -13
- package/dist/lib/contract/types.js +4 -5
- package/dist/lib/decide/decide.js +13 -46
- package/dist/lib/detach/drivers/batch.js +83 -0
- package/dist/lib/detach/drivers/microtaskBatch.js +20 -72
- package/dist/lib/detach/drivers/setImmediate.js +10 -41
- package/dist/lib/detach/drivers/setTimeout.js +3 -36
- package/dist/lib/detach/types.js +9 -11
- package/dist/lib/engine/handlers/ChildrenExecutor.js +7 -3
- package/dist/lib/engine/handlers/DeciderHandler.js +7 -5
- package/dist/lib/engine/handlers/ParallelForEachHandler.js +21 -24
- package/dist/lib/engine/handlers/SelectorHandler.js +15 -7
- package/dist/lib/engine/handlers/StageRunner.js +11 -22
- package/dist/lib/engine/handlers/SubflowExecutor.js +32 -17
- package/dist/lib/engine/handlers/SubflowInputMapper.js +19 -8
- package/dist/lib/engine/handlers/breakFlag.js +13 -0
- package/dist/lib/engine/handlers/commitStage.js +2 -2
- package/dist/lib/engine/handlers/servedPause.js +30 -0
- package/dist/lib/engine/handlers/stageError.js +34 -0
- package/dist/lib/engine/narrative/CombinedNarrativeRecorder.js +40 -67
- package/dist/lib/engine/narrative/FlowRecorderDispatcher.js +4 -8
- package/dist/lib/engine/narrative/NarrativeFlowRecorder.js +28 -48
- package/dist/lib/engine/narrative/formatting/resolveText.js +13 -0
- package/dist/lib/engine/narrative/formatting/sentences.js +63 -0
- package/dist/lib/engine/narrative/narrativeTypes.js +1 -1
- package/dist/lib/engine/narrative/recorders/RLENarrativeFlowRecorder.js +3 -7
- package/dist/lib/engine/narrative/recorders/SeparateNarrativeFlowRecorder.js +3 -7
- package/dist/lib/engine/narrative/recorders/WindowedNarrativeFlowRecorder.js +5 -10
- package/dist/lib/engine/narrative/types.js +1 -1
- package/dist/lib/engine/traversal/FlowchartTraverser.js +64 -33
- package/dist/lib/engine/types.js +1 -1
- package/dist/lib/memory/DiagnosticCollector.js +53 -9
- package/dist/lib/memory/EventLog.js +24 -1
- package/dist/lib/memory/StageContext.js +61 -7
- package/dist/lib/memory/eventPosition.js +3 -0
- package/dist/lib/memory/merge.js +15 -4
- package/dist/lib/memory/redaction.js +997 -33
- package/dist/lib/observer-queue/deferredDispatcher.js +3 -3
- package/dist/lib/observer-queue/index.js +8 -5
- package/dist/lib/pause/index.js +1 -1
- package/dist/lib/pause/record.js +19 -1
- package/dist/lib/pause/types.js +1 -1
- package/dist/lib/reactive/createTypedScope.js +19 -20
- package/dist/lib/reactive/index.js +2 -5
- package/dist/lib/reactive/types.js +2 -24
- package/dist/lib/recorder/EmitRecorder.js +1 -1
- package/dist/lib/recorder/InOutRecorder.js +6 -3
- package/dist/lib/runner/DeferredObserverTier.js +5 -4
- package/dist/lib/runner/ExecutionRuntime.js +2 -1
- package/dist/lib/runner/FlowChartExecutor.js +18 -10
- package/dist/lib/runner/attach.js +21 -31
- package/dist/lib/runner/checkpoint.js +4 -1
- package/dist/lib/scope/ScopeFacade.js +60 -39
- package/dist/lib/scope/protection/createProtectedScope.js +5 -2
- package/dist/lib/scope/protection/readonlyInput.js +74 -10
- package/dist/lib/scope/providers/baseStateCompatible.js +37 -36
- package/dist/lib/scope/providers/providers.js +3 -3
- package/dist/lib/scope/providers/resolve.js +2 -2
- package/dist/lib/scope/providers/types.js +1 -1
- package/dist/lib/scope/recorders/MetricRecorder.js +11 -14
- package/dist/lib/scope/runtime.js +67 -0
- package/dist/lib/scope/state/zod/defineScopeFromZod.js +15 -4
- package/dist/lib/scope/state/zod/resolver.js +3 -15
- package/dist/lib/scope/state/zod/scopeFactory.js +58 -22
- package/dist/lib/scope/state/zod/utils/validateHelper.js +70 -68
- package/dist/recorders.js +1 -1
- package/dist/types/advanced.d.ts +3 -1
- package/dist/types/index.d.ts +3 -3
- package/dist/types/lib/builder/FlowChartBuilder.d.ts +14 -4
- package/dist/types/lib/builder/types.d.ts +2 -3
- package/dist/types/lib/capture/freeze.d.ts +5 -5
- package/dist/types/lib/contract/index.d.ts +5 -8
- package/dist/types/lib/contract/types.d.ts +3 -81
- package/dist/types/lib/detach/drivers/batch.d.ts +9 -0
- package/dist/types/lib/detach/drivers/microtaskBatch.d.ts +17 -20
- package/dist/types/lib/detach/types.d.ts +17 -20
- package/dist/types/lib/engine/handlers/ParallelForEachHandler.d.ts +2 -3
- package/dist/types/lib/engine/handlers/SelectorHandler.d.ts +2 -4
- package/dist/types/lib/engine/handlers/SubflowInputMapper.d.ts +4 -3
- package/dist/types/lib/engine/handlers/breakFlag.d.ts +3 -0
- package/dist/types/lib/engine/handlers/servedPause.d.ts +15 -0
- package/dist/types/lib/engine/handlers/stageError.d.ts +20 -0
- package/dist/types/lib/engine/narrative/CombinedNarrativeRecorder.d.ts +6 -1
- package/dist/types/lib/engine/narrative/FlowRecorderDispatcher.d.ts +3 -3
- package/dist/types/lib/engine/narrative/NarrativeFlowRecorder.d.ts +7 -1
- package/dist/types/lib/engine/narrative/formatting/resolveText.d.ts +6 -0
- package/dist/types/lib/engine/narrative/formatting/sentences.d.ts +16 -0
- package/dist/types/lib/engine/narrative/narrativeTypes.d.ts +2 -0
- package/dist/types/lib/engine/narrative/recorders/WindowedNarrativeFlowRecorder.d.ts +0 -1
- package/dist/types/lib/engine/narrative/types.d.ts +18 -8
- package/dist/types/lib/engine/traversal/FlowchartTraverser.d.ts +8 -3
- package/dist/types/lib/engine/types.d.ts +4 -0
- package/dist/types/lib/memory/DiagnosticCollector.d.ts +12 -0
- package/dist/types/lib/memory/EventLog.d.ts +9 -0
- package/dist/types/lib/memory/StageContext.d.ts +22 -1
- package/dist/types/lib/memory/eventPosition.d.ts +18 -0
- package/dist/types/lib/memory/merge.d.ts +2 -1
- package/dist/types/lib/memory/redaction.d.ts +339 -17
- package/dist/types/lib/observer-queue/deferredDispatcher.d.ts +2 -2
- package/dist/types/lib/observer-queue/index.d.ts +7 -4
- package/dist/types/lib/pause/index.d.ts +1 -1
- package/dist/types/lib/pause/types.d.ts +20 -0
- package/dist/types/lib/reactive/index.d.ts +1 -1
- package/dist/types/lib/reactive/types.d.ts +0 -3
- package/dist/types/lib/recorder/EmitRecorder.d.ts +9 -0
- package/dist/types/lib/recorder/InOutRecorder.d.ts +5 -2
- package/dist/types/lib/runner/DeferredObserverTier.d.ts +4 -3
- package/dist/types/lib/runner/ExecutionRuntime.d.ts +3 -0
- package/dist/types/lib/runner/FlowChartExecutor.d.ts +11 -9
- package/dist/types/lib/runner/attach.d.ts +3 -1
- package/dist/types/lib/runner/checkpoint.d.ts +3 -1
- package/dist/types/lib/scope/ScopeFacade.d.ts +13 -1
- package/dist/types/lib/scope/protection/readonlyInput.d.ts +16 -6
- package/dist/types/lib/scope/providers/baseStateCompatible.d.ts +10 -24
- package/dist/types/lib/scope/providers/providers.d.ts +2 -2
- package/dist/types/lib/scope/providers/types.d.ts +4 -2
- package/dist/types/lib/scope/recorders/MetricRecorder.d.ts +2 -3
- package/dist/types/lib/scope/runtime.d.ts +48 -0
- package/dist/types/lib/scope/state/zod/defineScopeFromZod.d.ts +2 -2
- package/dist/types/lib/scope/state/zod/scopeFactory.d.ts +7 -3
- package/dist/types/lib/scope/state/zod/utils/validateHelper.d.ts +27 -18
- package/dist/types/recorders.d.ts +3 -0
- package/package.json +4 -3
- package/dist/esm/lib/contract/defineContract.d.ts +0 -18
- package/dist/esm/lib/contract/defineContract.js +0 -64
- package/dist/esm/lib/contract/openapi.d.ts +0 -18
- package/dist/esm/lib/contract/openapi.js +0 -98
- package/dist/lib/contract/defineContract.js +0 -68
- package/dist/lib/contract/openapi.js +0 -102
- package/dist/types/lib/contract/defineContract.d.ts +0 -18
- package/dist/types/lib/contract/openapi.d.ts +0 -18
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One lifecycle for the three deferred batching drivers. Adapters supply
|
|
3
|
+
* the deferral mechanism; this module owns each batch from registration
|
|
4
|
+
* through dispatch or refusal, and each child's terminal cleanup.
|
|
5
|
+
* Internal only: the consumer contract remains `types.ts · DetachDriver`.
|
|
6
|
+
*/
|
|
7
|
+
import { extractErrorInfo } from '../../errors/errorInfo.js';
|
|
8
|
+
import { asImpl, createHandle } from '../handle.js';
|
|
9
|
+
import { register, unregister } from '../registry.js';
|
|
10
|
+
export function createBatchSchedule(defer, runChild) {
|
|
11
|
+
let pending;
|
|
12
|
+
// Taking a batch retires its callback and releases its captured inputs.
|
|
13
|
+
// A callback captured by a scheduler that then threw must never take
|
|
14
|
+
// a newer batch. Retire BEFORE children/error formatting can re-enter.
|
|
15
|
+
function take(batch) {
|
|
16
|
+
if (pending !== batch)
|
|
17
|
+
return [];
|
|
18
|
+
pending = undefined;
|
|
19
|
+
return batch.splice(0);
|
|
20
|
+
}
|
|
21
|
+
return (child, input, refId) => {
|
|
22
|
+
const handle = createHandle(refId);
|
|
23
|
+
register(handle);
|
|
24
|
+
const item = { child, input, handle };
|
|
25
|
+
if (pending) {
|
|
26
|
+
pending.push(item);
|
|
27
|
+
return handle;
|
|
28
|
+
}
|
|
29
|
+
const batch = [item];
|
|
30
|
+
pending = batch;
|
|
31
|
+
try {
|
|
32
|
+
defer(() => {
|
|
33
|
+
// Start siblings in order without awaiting them. Reentrant
|
|
34
|
+
// scheduling belongs to a fresh batch with its own callback.
|
|
35
|
+
for (const work of take(batch)) {
|
|
36
|
+
executeOne(work, runChild).then(undefined, undefined);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
const refused = take(batch);
|
|
42
|
+
if (refused.length > 0) {
|
|
43
|
+
const failure = asError(error);
|
|
44
|
+
for (const work of refused) {
|
|
45
|
+
asImpl(work.handle)._markFailed(failure);
|
|
46
|
+
unregister(work.handle.id);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return handle;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
async function executeOne(item, runChild) {
|
|
54
|
+
const impl = asImpl(item.handle);
|
|
55
|
+
impl._markRunning();
|
|
56
|
+
try {
|
|
57
|
+
impl._markDone(await runChild(item.child, item.input));
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
impl._markFailed(asError(error));
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
unregister(impl.id);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function asError(error) {
|
|
67
|
+
try {
|
|
68
|
+
if (error instanceof Error)
|
|
69
|
+
return error;
|
|
70
|
+
return new Error(extractErrorInfo(error).message);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// Even classification can invoke user code (for example a revoked
|
|
74
|
+
// or stateful Proxy). Describing a refusal must not prevent it from
|
|
75
|
+
// settling the handle. Do not inspect the thrown value again here.
|
|
76
|
+
return new Error('Detached work failed; its thrown value could not be described.');
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmF0Y2guanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL2RldGFjaC9kcml2ZXJzL2JhdGNoLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7OztHQUtHO0FBR0gsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDN0QsT0FBTyxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDcEQsT0FBTyxFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQVV0RCxNQUFNLFVBQVUsbUJBQW1CLENBQ2pDLEtBQWtDLEVBQ2xDLFFBQXFCO0lBRXJCLElBQUksT0FBK0IsQ0FBQztJQUVwQyx3RUFBd0U7SUFDeEUscUVBQXFFO0lBQ3JFLHVFQUF1RTtJQUN2RSxTQUFTLElBQUksQ0FBQyxLQUFpQjtRQUM3QixJQUFJLE9BQU8sS0FBSyxLQUFLO1lBQUUsT0FBTyxFQUFFLENBQUM7UUFDakMsT0FBTyxHQUFHLFNBQVMsQ0FBQztRQUNwQixPQUFPLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDekIsQ0FBQztJQUVELE9BQU8sQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxFQUFFO1FBQzdCLE1BQU0sTUFBTSxHQUFHLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNuQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDakIsTUFBTSxJQUFJLEdBQUcsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxDQUFDO1FBQ3RDLElBQUksT0FBTyxFQUFFLENBQUM7WUFDWixPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ25CLE9BQU8sTUFBTSxDQUFDO1FBQ2hCLENBQUM7UUFFRCxNQUFNLEtBQUssR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3JCLE9BQU8sR0FBRyxLQUFLLENBQUM7UUFDaEIsSUFBSSxDQUFDO1lBQ0gsS0FBSyxDQUFDLEdBQUcsRUFBRTtnQkFDVCwyREFBMkQ7Z0JBQzNELDZEQUE2RDtnQkFDN0QsS0FBSyxNQUFNLElBQUksSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztvQkFDL0IsVUFBVSxDQUFDLElBQUksRUFBRSxRQUFRLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFDO2dCQUN4RCxDQUFDO1lBQ0gsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUM1QixJQUFJLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQ3ZCLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDL0IsS0FBSyxNQUFNLElBQUksSUFBSSxPQUFPLEVBQUUsQ0FBQztvQkFDM0IsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUM7b0JBQ3pDLFVBQVUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUM3QixDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7UUFDRCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDLENBQUM7QUFDSixDQUFDO0FBRUQsS0FBSyxVQUFVLFVBQVUsQ0FBQyxJQUFjLEVBQUUsUUFBcUI7SUFDN0QsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNqQyxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDcEIsSUFBSSxDQUFDO1FBQ0gsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLFFBQVEsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQ3pELENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2YsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUNuQyxDQUFDO1lBQVMsQ0FBQztRQUNULFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDdEIsQ0FBQztBQUNILENBQUM7QUFFRCxTQUFTLE9BQU8sQ0FBQyxLQUFjO0lBQzdCLElBQUksQ0FBQztRQUNILElBQUksS0FBSyxZQUFZLEtBQUs7WUFBRSxPQUFPLEtBQUssQ0FBQztRQUN6QyxPQUFPLElBQUksS0FBSyxDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3BELENBQUM7SUFBQyxNQUFNLENBQUM7UUFDUCxrRUFBa0U7UUFDbEUsb0VBQW9FO1FBQ3BFLG1FQUFtRTtRQUNuRSxPQUFPLElBQUksS0FBSyxDQUFDLGdFQUFnRSxDQUFDLENBQUM7SUFDckYsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIE9uZSBsaWZlY3ljbGUgZm9yIHRoZSB0aHJlZSBkZWZlcnJlZCBiYXRjaGluZyBkcml2ZXJzLiBBZGFwdGVycyBzdXBwbHlcbiAqIHRoZSBkZWZlcnJhbCBtZWNoYW5pc207IHRoaXMgbW9kdWxlIG93bnMgZWFjaCBiYXRjaCBmcm9tIHJlZ2lzdHJhdGlvblxuICogdGhyb3VnaCBkaXNwYXRjaCBvciByZWZ1c2FsLCBhbmQgZWFjaCBjaGlsZCdzIHRlcm1pbmFsIGNsZWFudXAuXG4gKiBJbnRlcm5hbCBvbmx5OiB0aGUgY29uc3VtZXIgY29udHJhY3QgcmVtYWlucyBgdHlwZXMudHMgwrcgRGV0YWNoRHJpdmVyYC5cbiAqL1xuXG5pbXBvcnQgdHlwZSB7IEZsb3dDaGFydCB9IGZyb20gJy4uLy4uL2J1aWxkZXIvdHlwZXMuanMnO1xuaW1wb3J0IHsgZXh0cmFjdEVycm9ySW5mbyB9IGZyb20gJy4uLy4uL2Vycm9ycy9lcnJvckluZm8uanMnO1xuaW1wb3J0IHsgYXNJbXBsLCBjcmVhdGVIYW5kbGUgfSBmcm9tICcuLi9oYW5kbGUuanMnO1xuaW1wb3J0IHsgcmVnaXN0ZXIsIHVucmVnaXN0ZXIgfSBmcm9tICcuLi9yZWdpc3RyeS5qcyc7XG5pbXBvcnQgdHlwZSB7IENoaWxkUnVubmVyIH0gZnJvbSAnLi4vcnVuQ2hpbGQuanMnO1xuaW1wb3J0IHR5cGUgeyBEZXRhY2hEcml2ZXIsIERldGFjaEhhbmRsZSB9IGZyb20gJy4uL3R5cGVzLmpzJztcblxuaW50ZXJmYWNlIFdvcmtJdGVtIHtcbiAgcmVhZG9ubHkgY2hpbGQ6IEZsb3dDaGFydDtcbiAgcmVhZG9ubHkgaW5wdXQ6IHVua25vd247XG4gIHJlYWRvbmx5IGhhbmRsZTogRGV0YWNoSGFuZGxlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQmF0Y2hTY2hlZHVsZShcbiAgZGVmZXI6IChmbHVzaDogKCkgPT4gdm9pZCkgPT4gdm9pZCxcbiAgcnVuQ2hpbGQ6IENoaWxkUnVubmVyLFxuKTogRGV0YWNoRHJpdmVyWydzY2hlZHVsZSddIHtcbiAgbGV0IHBlbmRpbmc6IFdvcmtJdGVtW10gfCB1bmRlZmluZWQ7XG5cbiAgLy8gVGFraW5nIGEgYmF0Y2ggcmV0aXJlcyBpdHMgY2FsbGJhY2sgYW5kIHJlbGVhc2VzIGl0cyBjYXB0dXJlZCBpbnB1dHMuXG4gIC8vIEEgY2FsbGJhY2sgY2FwdHVyZWQgYnkgYSBzY2hlZHVsZXIgdGhhdCB0aGVuIHRocmV3IG11c3QgbmV2ZXIgdGFrZVxuICAvLyBhIG5ld2VyIGJhdGNoLiBSZXRpcmUgQkVGT1JFIGNoaWxkcmVuL2Vycm9yIGZvcm1hdHRpbmcgY2FuIHJlLWVudGVyLlxuICBmdW5jdGlvbiB0YWtlKGJhdGNoOiBXb3JrSXRlbVtdKTogV29ya0l0ZW1bXSB7XG4gICAgaWYgKHBlbmRpbmcgIT09IGJhdGNoKSByZXR1cm4gW107XG4gICAgcGVuZGluZyA9IHVuZGVmaW5lZDtcbiAgICByZXR1cm4gYmF0Y2guc3BsaWNlKDApO1xuICB9XG5cbiAgcmV0dXJuIChjaGlsZCwgaW5wdXQsIHJlZklkKSA9PiB7XG4gICAgY29uc3QgaGFuZGxlID0gY3JlYXRlSGFuZGxlKHJlZklkKTtcbiAgICByZWdpc3RlcihoYW5kbGUpO1xuICAgIGNvbnN0IGl0ZW0gPSB7IGNoaWxkLCBpbnB1dCwgaGFuZGxlIH07XG4gICAgaWYgKHBlbmRpbmcpIHtcbiAgICAgIHBlbmRpbmcucHVzaChpdGVtKTtcbiAgICAgIHJldHVybiBoYW5kbGU7XG4gICAgfVxuXG4gICAgY29uc3QgYmF0Y2ggPSBbaXRlbV07XG4gICAgcGVuZGluZyA9IGJhdGNoO1xuICAgIHRyeSB7XG4gICAgICBkZWZlcigoKSA9PiB7XG4gICAgICAgIC8vIFN0YXJ0IHNpYmxpbmdzIGluIG9yZGVyIHdpdGhvdXQgYXdhaXRpbmcgdGhlbS4gUmVlbnRyYW50XG4gICAgICAgIC8vIHNjaGVkdWxpbmcgYmVsb25ncyB0byBhIGZyZXNoIGJhdGNoIHdpdGggaXRzIG93biBjYWxsYmFjay5cbiAgICAgICAgZm9yIChjb25zdCB3b3JrIG9mIHRha2UoYmF0Y2gpKSB7XG4gICAgICAgICAgZXhlY3V0ZU9uZSh3b3JrLCBydW5DaGlsZCkudGhlbih1bmRlZmluZWQsIHVuZGVmaW5lZCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zdCByZWZ1c2VkID0gdGFrZShiYXRjaCk7XG4gICAgICBpZiAocmVmdXNlZC5sZW5ndGggPiAwKSB7XG4gICAgICAgIGNvbnN0IGZhaWx1cmUgPSBhc0Vycm9yKGVycm9yKTtcbiAgICAgICAgZm9yIChjb25zdCB3b3JrIG9mIHJlZnVzZWQpIHtcbiAgICAgICAgICBhc0ltcGwod29yay5oYW5kbGUpLl9tYXJrRmFpbGVkKGZhaWx1cmUpO1xuICAgICAgICAgIHVucmVnaXN0ZXIod29yay5oYW5kbGUuaWQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBoYW5kbGU7XG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGV4ZWN1dGVPbmUoaXRlbTogV29ya0l0ZW0sIHJ1bkNoaWxkOiBDaGlsZFJ1bm5lcik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBpbXBsID0gYXNJbXBsKGl0ZW0uaGFuZGxlKTtcbiAgaW1wbC5fbWFya1J1bm5pbmcoKTtcbiAgdHJ5IHtcbiAgICBpbXBsLl9tYXJrRG9uZShhd2FpdCBydW5DaGlsZChpdGVtLmNoaWxkLCBpdGVtLmlucHV0KSk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgaW1wbC5fbWFya0ZhaWxlZChhc0Vycm9yKGVycm9yKSk7XG4gIH0gZmluYWxseSB7XG4gICAgdW5yZWdpc3RlcihpbXBsLmlkKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBhc0Vycm9yKGVycm9yOiB1bmtub3duKTogRXJyb3Ige1xuICB0cnkge1xuICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIEVycm9yKSByZXR1cm4gZXJyb3I7XG4gICAgcmV0dXJuIG5ldyBFcnJvcihleHRyYWN0RXJyb3JJbmZvKGVycm9yKS5tZXNzYWdlKTtcbiAgfSBjYXRjaCB7XG4gICAgLy8gRXZlbiBjbGFzc2lmaWNhdGlvbiBjYW4gaW52b2tlIHVzZXIgY29kZSAoZm9yIGV4YW1wbGUgYSByZXZva2VkXG4gICAgLy8gb3Igc3RhdGVmdWwgUHJveHkpLiBEZXNjcmliaW5nIGEgcmVmdXNhbCBtdXN0IG5vdCBwcmV2ZW50IGl0IGZyb21cbiAgICAvLyBzZXR0bGluZyB0aGUgaGFuZGxlLiBEbyBub3QgaW5zcGVjdCB0aGUgdGhyb3duIHZhbHVlIGFnYWluIGhlcmUuXG4gICAgcmV0dXJuIG5ldyBFcnJvcignRGV0YWNoZWQgd29yayBmYWlsZWQ7IGl0cyB0aHJvd24gdmFsdWUgY291bGQgbm90IGJlIGRlc2NyaWJlZC4nKTtcbiAgfVxufVxuIl19
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* detach/drivers/microtaskBatch.ts — Batch detached work into ONE microtask.
|
|
3
3
|
*
|
|
4
|
-
* Pattern: Producer-consumer with batched flush
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Pattern: Producer-consumer with batched flush — accumulate during
|
|
5
|
+
* the current sync slice, drain at the next microtask boundary.
|
|
6
|
+
* `batch.ts · createBatchSchedule` owns the lifecycle shared
|
|
7
|
+
* with the timeout and immediate-tick drivers.
|
|
8
8
|
* Role: The in-process driver the docs name (no driver is the default:
|
|
9
|
-
* every detach call passes one).
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* (queueMicrotask is universal since 2018).
|
|
9
|
+
* every detach call passes one). One `queueMicrotask` per
|
|
10
|
+
* batch amortizes scheduling cost across its work items.
|
|
11
|
+
* Suitable for browser, Node and edge runtimes that provide
|
|
12
|
+
* `queueMicrotask`.
|
|
14
13
|
*
|
|
15
14
|
* Lifecycle:
|
|
16
15
|
*
|
|
@@ -18,7 +17,8 @@
|
|
|
18
17
|
* └─ create handle (queued)
|
|
19
18
|
* └─ register in detachRegistry
|
|
20
19
|
* └─ push work item onto local queue
|
|
21
|
-
* └─ if
|
|
20
|
+
* └─ if this is a new batch → queueMicrotask(flush)
|
|
21
|
+
* └─ on scheduling failure → retire batch, fail + unregister handles
|
|
22
22
|
* └─ return handle (sync — passive recorder rule)
|
|
23
23
|
*
|
|
24
24
|
* flush() (microtask) ← deferred
|
|
@@ -27,18 +27,15 @@
|
|
|
27
27
|
* └─ unregister handle from detachRegistry
|
|
28
28
|
*
|
|
29
29
|
* Why microtask (and not setImmediate / setTimeout):
|
|
30
|
-
* - Microtasks
|
|
31
|
-
*
|
|
32
|
-
* -
|
|
33
|
-
* - Works in EVERY JS runtime (browser, node, deno, bun, edge)
|
|
34
|
-
* - Doesn't require any timer infrastructure → no GC pressure
|
|
30
|
+
* - Microtasks start BEFORE returning to the event loop; an async
|
|
31
|
+
* child can still finish on a later tick
|
|
32
|
+
* - No timer delay or Node-only scheduling API is required
|
|
35
33
|
*
|
|
36
34
|
* Re-entrancy:
|
|
37
|
-
* -
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* -
|
|
41
|
-
* real-world detach trees are shallow.
|
|
35
|
+
* - A flush retires its batch before starting children. If `runChild`
|
|
36
|
+
* calls `schedule()` for nested detach, it opens a fresh batch and
|
|
37
|
+
* schedules a new microtask.
|
|
38
|
+
* - A chain of n nested detaches needs n microtask boundaries
|
|
42
39
|
*/
|
|
43
40
|
import { type ChildRunner } from '../runChild.js';
|
|
44
41
|
import type { DetachDriver } from '../types.js';
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* detach/drivers/microtaskBatch.ts — Batch detached work into ONE microtask.
|
|
3
3
|
*
|
|
4
|
-
* Pattern: Producer-consumer with batched flush
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Pattern: Producer-consumer with batched flush — accumulate during
|
|
5
|
+
* the current sync slice, drain at the next microtask boundary.
|
|
6
|
+
* `batch.ts · createBatchSchedule` owns the lifecycle shared
|
|
7
|
+
* with the timeout and immediate-tick drivers.
|
|
8
8
|
* Role: The in-process driver the docs name (no driver is the default:
|
|
9
|
-
* every detach call passes one).
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* (queueMicrotask is universal since 2018).
|
|
9
|
+
* every detach call passes one). One `queueMicrotask` per
|
|
10
|
+
* batch amortizes scheduling cost across its work items.
|
|
11
|
+
* Suitable for browser, Node and edge runtimes that provide
|
|
12
|
+
* `queueMicrotask`.
|
|
14
13
|
*
|
|
15
14
|
* Lifecycle:
|
|
16
15
|
*
|
|
@@ -18,7 +17,8 @@
|
|
|
18
17
|
* └─ create handle (queued)
|
|
19
18
|
* └─ register in detachRegistry
|
|
20
19
|
* └─ push work item onto local queue
|
|
21
|
-
* └─ if
|
|
20
|
+
* └─ if this is a new batch → queueMicrotask(flush)
|
|
21
|
+
* └─ on scheduling failure → retire batch, fail + unregister handles
|
|
22
22
|
* └─ return handle (sync — passive recorder rule)
|
|
23
23
|
*
|
|
24
24
|
* flush() (microtask) ← deferred
|
|
@@ -27,22 +27,18 @@
|
|
|
27
27
|
* └─ unregister handle from detachRegistry
|
|
28
28
|
*
|
|
29
29
|
* Why microtask (and not setImmediate / setTimeout):
|
|
30
|
-
* - Microtasks
|
|
31
|
-
*
|
|
32
|
-
* -
|
|
33
|
-
* - Works in EVERY JS runtime (browser, node, deno, bun, edge)
|
|
34
|
-
* - Doesn't require any timer infrastructure → no GC pressure
|
|
30
|
+
* - Microtasks start BEFORE returning to the event loop; an async
|
|
31
|
+
* child can still finish on a later tick
|
|
32
|
+
* - No timer delay or Node-only scheduling API is required
|
|
35
33
|
*
|
|
36
34
|
* Re-entrancy:
|
|
37
|
-
* -
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* -
|
|
41
|
-
* real-world detach trees are shallow.
|
|
35
|
+
* - A flush retires its batch before starting children. If `runChild`
|
|
36
|
+
* calls `schedule()` for nested detach, it opens a fresh batch and
|
|
37
|
+
* schedules a new microtask.
|
|
38
|
+
* - A chain of n nested detaches needs n microtask boundaries
|
|
42
39
|
*/
|
|
43
|
-
import { asImpl, createHandle } from '../handle.js';
|
|
44
|
-
import { register, unregister } from '../registry.js';
|
|
45
40
|
import { defaultRunChild } from '../runChild.js';
|
|
41
|
+
import { createBatchSchedule } from './batch.js';
|
|
46
42
|
/**
|
|
47
43
|
* Build a microtask-batch driver wired to a custom child runner. Most
|
|
48
44
|
* consumers want the default singleton `microtaskBatchDriver` instead;
|
|
@@ -51,64 +47,16 @@ import { defaultRunChild } from '../runChild.js';
|
|
|
51
47
|
* tracing context).
|
|
52
48
|
*/
|
|
53
49
|
export function createMicrotaskBatchDriver(runChild = defaultRunChild) {
|
|
54
|
-
// Per-driver-instance queue and flush guard. Closed over by `schedule`
|
|
55
|
-
// and `flush` so each call to `createMicrotaskBatchDriver` gets its
|
|
56
|
-
// own isolated batch (test isolation, multi-tenant scenarios).
|
|
57
|
-
const queue = [];
|
|
58
|
-
let scheduled = false;
|
|
59
|
-
function flush() {
|
|
60
|
-
// Reset BEFORE draining so re-entrant schedule()s during runChild
|
|
61
|
-
// queue a fresh microtask instead of joining the in-flight drain.
|
|
62
|
-
scheduled = false;
|
|
63
|
-
const items = queue.splice(0);
|
|
64
|
-
for (const item of items) {
|
|
65
|
-
// Each item runs concurrently — no awaits here, so the outer
|
|
66
|
-
// for-loop completes within this microtask. Errors inside
|
|
67
|
-
// `executeOne` are routed to the handle, not thrown. The promise
|
|
68
|
-
// is intentionally not awaited; ignore-promise-returned via the
|
|
69
|
-
// explicit no-op .then() pattern that the project's lint config
|
|
70
|
-
// accepts (vs `void`, which `no-void` rejects).
|
|
71
|
-
executeOne(item, runChild).then(undefined, undefined);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
50
|
return {
|
|
75
51
|
name: 'microtask-batch',
|
|
76
52
|
capabilities: { browserSafe: true, nodeSafe: true, edgeSafe: true },
|
|
77
|
-
schedule(
|
|
78
|
-
const handle = createHandle(refId);
|
|
79
|
-
register(handle);
|
|
80
|
-
queue.push({ child, input, handle });
|
|
81
|
-
if (!scheduled) {
|
|
82
|
-
scheduled = true;
|
|
83
|
-
queueMicrotask(flush);
|
|
84
|
-
}
|
|
85
|
-
return handle;
|
|
86
|
-
},
|
|
53
|
+
schedule: createBatchSchedule((flush) => queueMicrotask(flush), runChild),
|
|
87
54
|
};
|
|
88
55
|
}
|
|
89
|
-
/**
|
|
90
|
-
* Per-item execution. Marks the handle running, awaits the runner,
|
|
91
|
-
* routes outcome to the handle, cleans up the registry entry. Never
|
|
92
|
-
* throws — errors land on the handle (passive recorder rule).
|
|
93
|
-
*/
|
|
94
|
-
async function executeOne(item, runChild) {
|
|
95
|
-
const impl = asImpl(item.handle);
|
|
96
|
-
impl._markRunning();
|
|
97
|
-
try {
|
|
98
|
-
const result = await runChild(item.child, item.input);
|
|
99
|
-
impl._markDone(result);
|
|
100
|
-
}
|
|
101
|
-
catch (err) {
|
|
102
|
-
impl._markFailed(err instanceof Error ? err : new Error(String(err)));
|
|
103
|
-
}
|
|
104
|
-
finally {
|
|
105
|
-
unregister(impl.id);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
56
|
/**
|
|
109
57
|
* Ready-made singleton. Most consumers import this and pass it as the first
|
|
110
58
|
* argument: `executor.detachAndJoinLater(microtaskBatchDriver, child, input)`.
|
|
111
59
|
* It is not an implicit default — nothing picks a driver for you.
|
|
112
60
|
*/
|
|
113
61
|
export const microtaskBatchDriver = createMicrotaskBatchDriver();
|
|
114
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
62
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWljcm90YXNrQmF0Y2guanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL2RldGFjaC9kcml2ZXJzL21pY3JvdGFza0JhdGNoLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXNDRztBQUVILE9BQU8sRUFBb0IsZUFBZSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFbkUsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRWpEOzs7Ozs7R0FNRztBQUNILE1BQU0sVUFBVSwwQkFBMEIsQ0FBQyxXQUF3QixlQUFlO0lBQ2hGLE9BQU87UUFDTCxJQUFJLEVBQUUsaUJBQWlCO1FBQ3ZCLFlBQVksRUFBRSxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFO1FBQ25FLFFBQVEsRUFBRSxtQkFBbUIsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxFQUFFLFFBQVEsQ0FBQztLQUMxRSxDQUFDO0FBQ0osQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsTUFBTSxvQkFBb0IsR0FBaUIsMEJBQTBCLEVBQUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogZGV0YWNoL2RyaXZlcnMvbWljcm90YXNrQmF0Y2gudHMg4oCUIEJhdGNoIGRldGFjaGVkIHdvcmsgaW50byBPTkUgbWljcm90YXNrLlxuICpcbiAqIFBhdHRlcm46ICBQcm9kdWNlci1jb25zdW1lciB3aXRoIGJhdGNoZWQgZmx1c2gg4oCUIGFjY3VtdWxhdGUgZHVyaW5nXG4gKiAgICAgICAgICAgdGhlIGN1cnJlbnQgc3luYyBzbGljZSwgZHJhaW4gYXQgdGhlIG5leHQgbWljcm90YXNrIGJvdW5kYXJ5LlxuICogICAgICAgICAgIGBiYXRjaC50cyDCtyBjcmVhdGVCYXRjaFNjaGVkdWxlYCBvd25zIHRoZSBsaWZlY3ljbGUgc2hhcmVkXG4gKiAgICAgICAgICAgd2l0aCB0aGUgdGltZW91dCBhbmQgaW1tZWRpYXRlLXRpY2sgZHJpdmVycy5cbiAqIFJvbGU6ICAgICBUaGUgaW4tcHJvY2VzcyBkcml2ZXIgdGhlIGRvY3MgbmFtZSAobm8gZHJpdmVyIGlzIHRoZSBkZWZhdWx0OlxuICogICAgICAgICAgIGV2ZXJ5IGRldGFjaCBjYWxsIHBhc3NlcyBvbmUpLiBPbmUgYHF1ZXVlTWljcm90YXNrYCBwZXJcbiAqICAgICAgICAgICBiYXRjaCBhbW9ydGl6ZXMgc2NoZWR1bGluZyBjb3N0IGFjcm9zcyBpdHMgd29yayBpdGVtcy5cbiAqICAgICAgICAgICBTdWl0YWJsZSBmb3IgYnJvd3NlciwgTm9kZSBhbmQgZWRnZSBydW50aW1lcyB0aGF0IHByb3ZpZGVcbiAqICAgICAgICAgICBgcXVldWVNaWNyb3Rhc2tgLlxuICpcbiAqIExpZmVjeWNsZTpcbiAqXG4gKiAgIHNjaGVkdWxlKGNoaWxkLCBpbnB1dCwgcmVmSWQpICAgICAgICAgICAg4oaQIGRyaXZlciBlbnRyeVxuICogICAgIOKUlOKUgCBjcmVhdGUgaGFuZGxlIChxdWV1ZWQpXG4gKiAgICAg4pSU4pSAIHJlZ2lzdGVyIGluIGRldGFjaFJlZ2lzdHJ5XG4gKiAgICAg4pSU4pSAIHB1c2ggd29yayBpdGVtIG9udG8gbG9jYWwgcXVldWVcbiAqICAgICDilJTilIAgaWYgdGhpcyBpcyBhIG5ldyBiYXRjaCDihpIgcXVldWVNaWNyb3Rhc2soZmx1c2gpXG4gKiAgICAg4pSU4pSAIG9uIHNjaGVkdWxpbmcgZmFpbHVyZSDihpIgcmV0aXJlIGJhdGNoLCBmYWlsICsgdW5yZWdpc3RlciBoYW5kbGVzXG4gKiAgICAg4pSU4pSAIHJldHVybiBoYW5kbGUgKHN5bmMg4oCUIHBhc3NpdmUgcmVjb3JkZXIgcnVsZSlcbiAqXG4gKiAgIGZsdXNoKCkgKG1pY3JvdGFzaykgICAgICAgICAgICAgICAgICAgICAgIOKGkCBkZWZlcnJlZFxuICogICAgIOKUlOKUgCBzd2FwIG91dCBxdWV1ZSAoZHJhaW4gcmFjZXMgc2FmZWx5KVxuICogICAgIOKUlOKUgCBmb3IgZWFjaCBpdGVtOiBfbWFya1J1bm5pbmcsIGF3YWl0IHJ1bkNoaWxkLCBfbWFya0RvbmUvX21hcmtGYWlsZWRcbiAqICAgICDilJTilIAgdW5yZWdpc3RlciBoYW5kbGUgZnJvbSBkZXRhY2hSZWdpc3RyeVxuICpcbiAqIFdoeSBtaWNyb3Rhc2sgKGFuZCBub3Qgc2V0SW1tZWRpYXRlIC8gc2V0VGltZW91dCk6XG4gKiAgIC0gTWljcm90YXNrcyBzdGFydCBCRUZPUkUgcmV0dXJuaW5nIHRvIHRoZSBldmVudCBsb29wOyBhbiBhc3luY1xuICogICAgIGNoaWxkIGNhbiBzdGlsbCBmaW5pc2ggb24gYSBsYXRlciB0aWNrXG4gKiAgIC0gTm8gdGltZXIgZGVsYXkgb3IgTm9kZS1vbmx5IHNjaGVkdWxpbmcgQVBJIGlzIHJlcXVpcmVkXG4gKlxuICogUmUtZW50cmFuY3k6XG4gKiAgIC0gQSBmbHVzaCByZXRpcmVzIGl0cyBiYXRjaCBiZWZvcmUgc3RhcnRpbmcgY2hpbGRyZW4uIElmIGBydW5DaGlsZGBcbiAqICAgICBjYWxscyBgc2NoZWR1bGUoKWAgZm9yIG5lc3RlZCBkZXRhY2gsIGl0IG9wZW5zIGEgZnJlc2ggYmF0Y2ggYW5kXG4gKiAgICAgc2NoZWR1bGVzIGEgbmV3IG1pY3JvdGFzay5cbiAqICAgLSBBIGNoYWluIG9mIG4gbmVzdGVkIGRldGFjaGVzIG5lZWRzIG4gbWljcm90YXNrIGJvdW5kYXJpZXNcbiAqL1xuXG5pbXBvcnQgeyB0eXBlIENoaWxkUnVubmVyLCBkZWZhdWx0UnVuQ2hpbGQgfSBmcm9tICcuLi9ydW5DaGlsZC5qcyc7XG5pbXBvcnQgdHlwZSB7IERldGFjaERyaXZlciB9IGZyb20gJy4uL3R5cGVzLmpzJztcbmltcG9ydCB7IGNyZWF0ZUJhdGNoU2NoZWR1bGUgfSBmcm9tICcuL2JhdGNoLmpzJztcblxuLyoqXG4gKiBCdWlsZCBhIG1pY3JvdGFzay1iYXRjaCBkcml2ZXIgd2lyZWQgdG8gYSBjdXN0b20gY2hpbGQgcnVubmVyLiBNb3N0XG4gKiBjb25zdW1lcnMgd2FudCB0aGUgZGVmYXVsdCBzaW5nbGV0b24gYG1pY3JvdGFza0JhdGNoRHJpdmVyYCBpbnN0ZWFkO1xuICogdGhpcyBmYWN0b3J5IGV4aXN0cyBmb3IgdGVzdHMgYW5kIGZvciBhZHZhbmNlZCBjb25zdW1lcnMgd2hvIHdhbnQgdG9cbiAqIGluamVjdCB0aGVpciBvd24gcnVubmVyIChlLmcuLCBhIHJ1bm5lciB0aGF0IHdyYXBzIHRoZSBjaGlsZCBpbiBhXG4gKiB0cmFjaW5nIGNvbnRleHQpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlTWljcm90YXNrQmF0Y2hEcml2ZXIocnVuQ2hpbGQ6IENoaWxkUnVubmVyID0gZGVmYXVsdFJ1bkNoaWxkKTogRGV0YWNoRHJpdmVyIHtcbiAgcmV0dXJuIHtcbiAgICBuYW1lOiAnbWljcm90YXNrLWJhdGNoJyxcbiAgICBjYXBhYmlsaXRpZXM6IHsgYnJvd3NlclNhZmU6IHRydWUsIG5vZGVTYWZlOiB0cnVlLCBlZGdlU2FmZTogdHJ1ZSB9LFxuICAgIHNjaGVkdWxlOiBjcmVhdGVCYXRjaFNjaGVkdWxlKChmbHVzaCkgPT4gcXVldWVNaWNyb3Rhc2soZmx1c2gpLCBydW5DaGlsZCksXG4gIH07XG59XG5cbi8qKlxuICogUmVhZHktbWFkZSBzaW5nbGV0b24uIE1vc3QgY29uc3VtZXJzIGltcG9ydCB0aGlzIGFuZCBwYXNzIGl0IGFzIHRoZSBmaXJzdFxuICogYXJndW1lbnQ6IGBleGVjdXRvci5kZXRhY2hBbmRKb2luTGF0ZXIobWljcm90YXNrQmF0Y2hEcml2ZXIsIGNoaWxkLCBpbnB1dClgLlxuICogSXQgaXMgbm90IGFuIGltcGxpY2l0IGRlZmF1bHQg4oCUIG5vdGhpbmcgcGlja3MgYSBkcml2ZXIgZm9yIHlvdS5cbiAqL1xuZXhwb3J0IGNvbnN0IG1pY3JvdGFza0JhdGNoRHJpdmVyOiBEZXRhY2hEcml2ZXIgPSBjcmVhdGVNaWNyb3Rhc2tCYXRjaERyaXZlcigpO1xuIl19
|
|
@@ -26,56 +26,25 @@
|
|
|
26
26
|
* available in browsers / Deno / Cloudflare Workers (use
|
|
27
27
|
* `setTimeoutDriver` for cross-runtime alternative)
|
|
28
28
|
*/
|
|
29
|
-
import { asImpl, createHandle } from '../handle.js';
|
|
30
|
-
import { register, unregister } from '../registry.js';
|
|
31
29
|
import { defaultRunChild } from '../runChild.js';
|
|
30
|
+
import { createBatchSchedule } from './batch.js';
|
|
32
31
|
export function createSetImmediateDriver(runChild = defaultRunChild) {
|
|
33
|
-
const queue = [];
|
|
34
|
-
let scheduled = false;
|
|
35
|
-
function flush() {
|
|
36
|
-
scheduled = false;
|
|
37
|
-
const items = queue.splice(0);
|
|
38
|
-
for (const item of items) {
|
|
39
|
-
executeOne(item, runChild).then(undefined, undefined);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
32
|
return {
|
|
43
33
|
name: 'set-immediate',
|
|
44
34
|
capabilities: { nodeSafe: true },
|
|
45
35
|
validate() {
|
|
46
|
-
|
|
47
|
-
throw new Error('[detach] setImmediateDriver requires Node.js — global `setImmediate` is not defined ' +
|
|
48
|
-
'in this runtime. Use `microtaskBatchDriver` for cross-runtime use, or `setTimeoutDriver` ' +
|
|
49
|
-
'for browser/edge environments.');
|
|
50
|
-
}
|
|
51
|
-
},
|
|
52
|
-
schedule(child, input, refId) {
|
|
53
|
-
const handle = createHandle(refId);
|
|
54
|
-
register(handle);
|
|
55
|
-
queue.push({ child, input, handle });
|
|
56
|
-
if (!scheduled) {
|
|
57
|
-
scheduled = true;
|
|
58
|
-
// `setImmediate` is non-undefined here in Node; runtime guard
|
|
59
|
-
// is in `validate()`. The `!` is a deliberate assertion.
|
|
60
|
-
setImmediate(flush);
|
|
61
|
-
}
|
|
62
|
-
return handle;
|
|
36
|
+
scheduler();
|
|
63
37
|
},
|
|
38
|
+
schedule: createBatchSchedule((flush) => scheduler()(flush), runChild),
|
|
64
39
|
};
|
|
65
40
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
impl._markDone(result);
|
|
72
|
-
}
|
|
73
|
-
catch (err) {
|
|
74
|
-
impl._markFailed(err instanceof Error ? err : new Error(String(err)));
|
|
75
|
-
}
|
|
76
|
-
finally {
|
|
77
|
-
unregister(impl.id);
|
|
41
|
+
function scheduler() {
|
|
42
|
+
if (typeof setImmediate !== 'function') {
|
|
43
|
+
throw new Error('[detach] setImmediateDriver requires Node.js — global `setImmediate` is not defined ' +
|
|
44
|
+
'in this runtime. Use `microtaskBatchDriver` for cross-runtime use, or `setTimeoutDriver` ' +
|
|
45
|
+
'for browser/edge environments.');
|
|
78
46
|
}
|
|
47
|
+
return setImmediate;
|
|
79
48
|
}
|
|
80
49
|
export const setImmediateDriver = createSetImmediateDriver();
|
|
81
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
50
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2V0SW1tZWRpYXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9kZXRhY2gvZHJpdmVycy9zZXRJbW1lZGlhdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTJCRztBQUVILE9BQU8sRUFBb0IsZUFBZSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFbkUsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sWUFBWSxDQUFDO0FBUWpELE1BQU0sVUFBVSx3QkFBd0IsQ0FBQyxXQUF3QixlQUFlO0lBQzlFLE9BQU87UUFDTCxJQUFJLEVBQUUsZUFBZTtRQUNyQixZQUFZLEVBQUUsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFO1FBQ2hDLFFBQVE7WUFDTixTQUFTLEVBQUUsQ0FBQztRQUNkLENBQUM7UUFDRCxRQUFRLEVBQUUsbUJBQW1CLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLFNBQVMsRUFBRSxDQUFDLEtBQUssQ0FBQyxFQUFFLFFBQVEsQ0FBQztLQUN2RSxDQUFDO0FBQ0osQ0FBQztBQUVELFNBQVMsU0FBUztJQUNoQixJQUFJLE9BQU8sWUFBWSxLQUFLLFVBQVUsRUFBRSxDQUFDO1FBQ3ZDLE1BQU0sSUFBSSxLQUFLLENBQ2Isc0ZBQXNGO1lBQ3BGLDJGQUEyRjtZQUMzRixnQ0FBZ0MsQ0FDbkMsQ0FBQztJQUNKLENBQUM7SUFDRCxPQUFPLFlBQVksQ0FBQztBQUN0QixDQUFDO0FBRUQsTUFBTSxDQUFDLE1BQU0sa0JBQWtCLEdBQWlCLHdCQUF3QixFQUFFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIGRldGFjaC9kcml2ZXJzL3NldEltbWVkaWF0ZS50cyDigJQgRGVmZXIgZGV0YWNoZWQgd29yayB0byBhIE5vZGUuanNcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBzZXRJbW1lZGlhdGVgIGJvdW5kYXJ5LlxuICpcbiAqIFBhdHRlcm46ICBTYW1lIHByb2R1Y2VyLWNvbnN1bWVyIGJhdGNoIGZsdXNoIGFzIGBtaWNyb3Rhc2tCYXRjaGAsXG4gKiAgICAgICAgICAgYnV0IHRoZSBkZWZlcnJhbCBpcyBgc2V0SW1tZWRpYXRlYCBpbnN0ZWFkIG9mXG4gKiAgICAgICAgICAgYHF1ZXVlTWljcm90YXNrYC4gWWllbGRzIGNvbnRyb2wgYmFjayB0byB0aGUgZXZlbnQgbG9vcFxuICogICAgICAgICAgIEJFRk9SRSBydW5uaW5nIOKAlCBhbGxvd3MgcGVuZGluZyBJL08gY2FsbGJhY2tzIHRvIGRyYWluXG4gKiAgICAgICAgICAgZmlyc3QsIHdoaWNoIG1pY3JvdGFza3Mgd291bGQgYmxvY2suXG4gKiBSb2xlOiAgICAgTm9kZS1zcGVjaWZpYyBkcml2ZXIgZm9yIFwiZmlyZS1hbmQtZm9yZ2V0IGFmdGVyIHRoZVxuICogICAgICAgICAgIGN1cnJlbnQgSS9PIHRpY2suXCIgVXNlIHdoZW4gdGhlIHBhcmVudCBzdGFnZSBoYW5kbGVzXG4gKiAgICAgICAgICAgbGF0ZW5jeS1zZW5zaXRpdmUgd29yayBhbmQgeW91IGRvbid0IHdhbnQgZGV0YWNoZWQgd29ya1xuICogICAgICAgICAgIHRvIGNvbXBldGUgZm9yIHRoZSBzeW5jaHJvbm91cyBzbGljZS5cbiAqXG4gKiBXaGVuIHRvIHBpY2sgdGhpcyBvdmVyIG1pY3JvdGFza0JhdGNoOlxuICogICAtIFlvdSdyZSBzaGlwcGluZyBsb2dzIC8gbWV0cmljcyBpbiBhIGhvdCBIVFRQIHBhdGggYW5kIGRvbid0XG4gKiAgICAgd2FudCB0aGVtIGJsb2NraW5nIHRoZSByZXNwb25zZSBmcm9tIGJlaW5nIGZsdXNoZWRcbiAqICAgLSBUaGUgZGV0YWNoZWQgd29yayBpdHNlbGYgaXMgQ1BVLWhlYXZ5IGVub3VnaCB0aGF0IHJ1bm5pbmcgaXQgb25cbiAqICAgICB0aGUgc2FtZSBtaWNyb3Rhc2sgY3ljbGUgd291bGQgZGVsYXkgb3RoZXIgbWljcm90YXNrc1xuICogICAtIFlvdSBleHBsaWNpdGx5IHdhbnQgXCJuZXh0IGV2ZW50LWxvb3AgdGlja1wiIHNlbWFudGljcyDigJQgdXNlZnVsXG4gKiAgICAgd2hlbiBpbnRlcmFjdGluZyB3aXRoIHRoaXJkLXBhcnR5IGxpYnJhcmllcyB0aGF0IGV4cGVjdCBhdFxuICogICAgIGxlYXN0IG9uZSBJL08gdGljayBiZXR3ZWVuIHNjaGVkdWxlIGFuZCBleGVjdXRpb25cbiAqXG4gKiBDYXBhYmlsaXR5OlxuICogICAtIGBub2RlU2FmZTogdHJ1ZWAg4oCUIHJlbGllcyBvbiBOb2RlJ3MgYHNldEltbWVkaWF0ZWAsIE5PVFxuICogICAgIGF2YWlsYWJsZSBpbiBicm93c2VycyAvIERlbm8gLyBDbG91ZGZsYXJlIFdvcmtlcnMgKHVzZVxuICogICAgIGBzZXRUaW1lb3V0RHJpdmVyYCBmb3IgY3Jvc3MtcnVudGltZSBhbHRlcm5hdGl2ZSlcbiAqL1xuXG5pbXBvcnQgeyB0eXBlIENoaWxkUnVubmVyLCBkZWZhdWx0UnVuQ2hpbGQgfSBmcm9tICcuLi9ydW5DaGlsZC5qcyc7XG5pbXBvcnQgdHlwZSB7IERldGFjaERyaXZlciB9IGZyb20gJy4uL3R5cGVzLmpzJztcbmltcG9ydCB7IGNyZWF0ZUJhdGNoU2NoZWR1bGUgfSBmcm9tICcuL2JhdGNoLmpzJztcblxuLy8gTm9kZS1vbmx5IGdsb2JhbC4gV2UgZG9uJ3Qgc2hpcCBAdHlwZXMvbm9kZSwgc28gZGVjbGFyZSB0aGUgbWluaW1hbFxuLy8gc2hhcGUgaGVyZS4gYHNldEltbWVkaWF0ZURyaXZlcmAgYWR2ZXJ0aXNlcyBgbm9kZVNhZmU6IHRydWVgLlxuLy8gQm90aCBleHBsaWNpdCBwcmVmbGlnaHQgYW5kIHNjaGVkdWxpbmcgY2hlY2sgYXZhaWxhYmlsaXR5IGxhemlseSxcbi8vIHNvIGltcG9ydGluZyB0aGlzIG1vZHVsZSBkb2VzIG5vdCByZXF1aXJlIHRoZSBOb2RlLW9ubHkgZ2xvYmFsLlxuZGVjbGFyZSBjb25zdCBzZXRJbW1lZGlhdGU6ICgoY2I6ICgpID0+IHZvaWQpID0+IHVua25vd24pIHwgdW5kZWZpbmVkO1xuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlU2V0SW1tZWRpYXRlRHJpdmVyKHJ1bkNoaWxkOiBDaGlsZFJ1bm5lciA9IGRlZmF1bHRSdW5DaGlsZCk6IERldGFjaERyaXZlciB7XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ3NldC1pbW1lZGlhdGUnLFxuICAgIGNhcGFiaWxpdGllczogeyBub2RlU2FmZTogdHJ1ZSB9LFxuICAgIHZhbGlkYXRlKCk6IHZvaWQge1xuICAgICAgc2NoZWR1bGVyKCk7XG4gICAgfSxcbiAgICBzY2hlZHVsZTogY3JlYXRlQmF0Y2hTY2hlZHVsZSgoZmx1c2gpID0+IHNjaGVkdWxlcigpKGZsdXNoKSwgcnVuQ2hpbGQpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzY2hlZHVsZXIoKTogKGNiOiAoKSA9PiB2b2lkKSA9PiB1bmtub3duIHtcbiAgaWYgKHR5cGVvZiBzZXRJbW1lZGlhdGUgIT09ICdmdW5jdGlvbicpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAnW2RldGFjaF0gc2V0SW1tZWRpYXRlRHJpdmVyIHJlcXVpcmVzIE5vZGUuanMg4oCUIGdsb2JhbCBgc2V0SW1tZWRpYXRlYCBpcyBub3QgZGVmaW5lZCAnICtcbiAgICAgICAgJ2luIHRoaXMgcnVudGltZS4gVXNlIGBtaWNyb3Rhc2tCYXRjaERyaXZlcmAgZm9yIGNyb3NzLXJ1bnRpbWUgdXNlLCBvciBgc2V0VGltZW91dERyaXZlcmAgJyArXG4gICAgICAgICdmb3IgYnJvd3Nlci9lZGdlIGVudmlyb25tZW50cy4nLFxuICAgICk7XG4gIH1cbiAgcmV0dXJuIHNldEltbWVkaWF0ZTtcbn1cblxuZXhwb3J0IGNvbnN0IHNldEltbWVkaWF0ZURyaXZlcjogRGV0YWNoRHJpdmVyID0gY3JlYXRlU2V0SW1tZWRpYXRlRHJpdmVyKCk7XG4iXX0=
|
|
@@ -19,51 +19,18 @@
|
|
|
19
19
|
* - Browser tab freezing / throttling can extend the delay
|
|
20
20
|
* significantly. Don't rely on precise timing.
|
|
21
21
|
*/
|
|
22
|
-
import { asImpl, createHandle } from '../handle.js';
|
|
23
|
-
import { register, unregister } from '../registry.js';
|
|
24
22
|
import { defaultRunChild } from '../runChild.js';
|
|
23
|
+
import { createBatchSchedule } from './batch.js';
|
|
25
24
|
export function createSetTimeoutDriver(opts = {}) {
|
|
26
25
|
const delayMs = opts.delayMs ?? 0;
|
|
27
26
|
const runChild = opts.runChild ?? defaultRunChild;
|
|
28
|
-
const queue = [];
|
|
29
|
-
let scheduled = false;
|
|
30
|
-
function flush() {
|
|
31
|
-
scheduled = false;
|
|
32
|
-
const items = queue.splice(0);
|
|
33
|
-
for (const item of items) {
|
|
34
|
-
executeOne(item, runChild).then(undefined, undefined);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
27
|
return {
|
|
38
28
|
name: delayMs === 0 ? 'set-timeout' : `set-timeout-${delayMs}ms`,
|
|
39
29
|
capabilities: { browserSafe: true, nodeSafe: true, edgeSafe: true },
|
|
40
|
-
schedule(
|
|
41
|
-
const handle = createHandle(refId);
|
|
42
|
-
register(handle);
|
|
43
|
-
queue.push({ child, input, handle });
|
|
44
|
-
if (!scheduled) {
|
|
45
|
-
scheduled = true;
|
|
46
|
-
setTimeout(flush, delayMs);
|
|
47
|
-
}
|
|
48
|
-
return handle;
|
|
49
|
-
},
|
|
30
|
+
schedule: createBatchSchedule((flush) => setTimeout(flush, delayMs), runChild),
|
|
50
31
|
};
|
|
51
32
|
}
|
|
52
|
-
async function executeOne(item, runChild) {
|
|
53
|
-
const impl = asImpl(item.handle);
|
|
54
|
-
impl._markRunning();
|
|
55
|
-
try {
|
|
56
|
-
const result = await runChild(item.child, item.input);
|
|
57
|
-
impl._markDone(result);
|
|
58
|
-
}
|
|
59
|
-
catch (err) {
|
|
60
|
-
impl._markFailed(err instanceof Error ? err : new Error(String(err)));
|
|
61
|
-
}
|
|
62
|
-
finally {
|
|
63
|
-
unregister(impl.id);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
33
|
/** Default singleton — zero-delay (next macrotask). For configurable
|
|
67
34
|
* delays, use `createSetTimeoutDriver({ delayMs })`. */
|
|
68
35
|
export const setTimeoutDriver = createSetTimeoutDriver();
|
|
69
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
36
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2V0VGltZW91dC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvZGV0YWNoL2RyaXZlcnMvc2V0VGltZW91dC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FvQkc7QUFFSCxPQUFPLEVBQW9CLGVBQWUsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRW5FLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLFlBQVksQ0FBQztBQVVqRCxNQUFNLFVBQVUsc0JBQXNCLENBQUMsT0FBZ0MsRUFBRTtJQUN2RSxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxJQUFJLENBQUMsQ0FBQztJQUNsQyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBUSxJQUFJLGVBQWUsQ0FBQztJQUNsRCxPQUFPO1FBQ0wsSUFBSSxFQUFFLE9BQU8sS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsZUFBZSxPQUFPLElBQUk7UUFDaEUsWUFBWSxFQUFFLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUU7UUFDbkUsUUFBUSxFQUFFLG1CQUFtQixDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxFQUFFLFFBQVEsQ0FBQztLQUMvRSxDQUFDO0FBQ0osQ0FBQztBQUVEO3lEQUN5RDtBQUN6RCxNQUFNLENBQUMsTUFBTSxnQkFBZ0IsR0FBaUIsc0JBQXNCLEVBQUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogZGV0YWNoL2RyaXZlcnMvc2V0VGltZW91dC50cyDigJQgRGVmZXIgZGV0YWNoZWQgd29yayB2aWEgYHNldFRpbWVvdXQoLi4uLCBkZWxheU1zKWAuXG4gKlxuICogUGF0dGVybjogIFByb2R1Y2VyLWNvbnN1bWVyIGJhdGNoIGZsdXNoOyBkZWZlcnJhbCBtZWNoYW5pc20gaXNcbiAqICAgICAgICAgICBgc2V0VGltZW91dGAgd2l0aCBhIGNvbmZpZ3VyYWJsZSBkZWxheSAoZGVmYXVsdCBgMGApLlxuICogUm9sZTogICAgIENyb3NzLXJ1bnRpbWUgXCJuZXh0IG1hY3JvdGFza1wiIGRyaXZlci4gV29ya3MgaW4gYnJvd3NlcnMsXG4gKiAgICAgICAgICAgTm9kZS5qcywgRGVubywgQ2xvdWRmbGFyZSBXb3JrZXJzLCBCdW4sIGV0Yy5cbiAqXG4gKiBXaGVuIHRvIHBpY2sgdGhpczpcbiAqICAgLSBDb25zdW1lciB3YW50cyBhIFNQRUNJRklDIGRlbGF5IChlLmcuIFwic2hpcCB0ZWxlbWV0cnkgaW4gNVxuICogICAgIHNlY29uZHMsIGJhdGNoZWRcIikg4oCUIHBhc3MgYGNyZWF0ZVNldFRpbWVvdXREcml2ZXIoeyBkZWxheU1zOiA1MDAwIH0pYFxuICogICAtIENyb3NzLXJ1bnRpbWUgZGV0YWNoIHdoZXJlIGBzZXRJbW1lZGlhdGVgIGlzbid0IGF2YWlsYWJsZVxuICogICAtIENvYWxlc2NpbmcgaGlnaC1mcmVxdWVuY3kgZXZlbnRzIGludG8gYSBsb3ctZnJlcXVlbmN5IGZsdXNoXG4gKlxuICogQ2F2ZWF0czpcbiAqICAgLSBOb3QgZm9yIGxvdy1sYXRlbmN5IGhvdCBwYXRocyDigJQgbWluaW11bSBkZWxheSBpcyB+NG1zIGluXG4gKiAgICAgYnJvd3NlcnMgcGVyIHRoZSBIVE1MNSBzcGVjLCB+MW1zIGluIE5vZGUuIFVzZVxuICogICAgIGBtaWNyb3Rhc2tCYXRjaERyaXZlcmAgZm9yIHN1Yi1tcyBzY2hlZHVsaW5nLlxuICogICAtIEJyb3dzZXIgdGFiIGZyZWV6aW5nIC8gdGhyb3R0bGluZyBjYW4gZXh0ZW5kIHRoZSBkZWxheVxuICogICAgIHNpZ25pZmljYW50bHkuIERvbid0IHJlbHkgb24gcHJlY2lzZSB0aW1pbmcuXG4gKi9cblxuaW1wb3J0IHsgdHlwZSBDaGlsZFJ1bm5lciwgZGVmYXVsdFJ1bkNoaWxkIH0gZnJvbSAnLi4vcnVuQ2hpbGQuanMnO1xuaW1wb3J0IHR5cGUgeyBEZXRhY2hEcml2ZXIgfSBmcm9tICcuLi90eXBlcy5qcyc7XG5pbXBvcnQgeyBjcmVhdGVCYXRjaFNjaGVkdWxlIH0gZnJvbSAnLi9iYXRjaC5qcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2V0VGltZW91dERyaXZlck9wdGlvbnMge1xuICAvKiogTWlsbGlzZWNvbmRzIHRvIHdhaXQgYmVmb3JlIGZsdXNoaW5nIHRoZSBiYXRjaC4gRGVmYXVsdCAwXG4gICAqICAobmV4dCBtYWNyb3Rhc2spLiAqL1xuICByZWFkb25seSBkZWxheU1zPzogbnVtYmVyO1xuICAvKiogQ3VzdG9tIGBydW5DaGlsZGAuIERlZmF1bHRzIHRvIHNwYXduaW5nIGEgYEZsb3dDaGFydEV4ZWN1dG9yYC4gKi9cbiAgcmVhZG9ubHkgcnVuQ2hpbGQ/OiBDaGlsZFJ1bm5lcjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVNldFRpbWVvdXREcml2ZXIob3B0czogU2V0VGltZW91dERyaXZlck9wdGlvbnMgPSB7fSk6IERldGFjaERyaXZlciB7XG4gIGNvbnN0IGRlbGF5TXMgPSBvcHRzLmRlbGF5TXMgPz8gMDtcbiAgY29uc3QgcnVuQ2hpbGQgPSBvcHRzLnJ1bkNoaWxkID8/IGRlZmF1bHRSdW5DaGlsZDtcbiAgcmV0dXJuIHtcbiAgICBuYW1lOiBkZWxheU1zID09PSAwID8gJ3NldC10aW1lb3V0JyA6IGBzZXQtdGltZW91dC0ke2RlbGF5TXN9bXNgLFxuICAgIGNhcGFiaWxpdGllczogeyBicm93c2VyU2FmZTogdHJ1ZSwgbm9kZVNhZmU6IHRydWUsIGVkZ2VTYWZlOiB0cnVlIH0sXG4gICAgc2NoZWR1bGU6IGNyZWF0ZUJhdGNoU2NoZWR1bGUoKGZsdXNoKSA9PiBzZXRUaW1lb3V0KGZsdXNoLCBkZWxheU1zKSwgcnVuQ2hpbGQpLFxuICB9O1xufVxuXG4vKiogRGVmYXVsdCBzaW5nbGV0b24g4oCUIHplcm8tZGVsYXkgKG5leHQgbWFjcm90YXNrKS4gRm9yIGNvbmZpZ3VyYWJsZVxuICogIGRlbGF5cywgdXNlIGBjcmVhdGVTZXRUaW1lb3V0RHJpdmVyKHsgZGVsYXlNcyB9KWAuICovXG5leHBvcnQgY29uc3Qgc2V0VGltZW91dERyaXZlcjogRGV0YWNoRHJpdmVyID0gY3JlYXRlU2V0VGltZW91dERyaXZlcigpO1xuIl19
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* detach/types.ts — Type definitions for the fire-and-forget primitive.
|
|
3
3
|
*
|
|
4
|
-
* Pattern:
|
|
5
|
-
* agentfootprint v2.6 — ONE interface, N concrete drivers,
|
|
4
|
+
* Pattern: One strategy interface, concrete scheduling drivers,
|
|
6
5
|
* consumer picks via explicit import.
|
|
7
6
|
* Role: Foundation. Every other detach file imports from here.
|
|
8
7
|
* This is the lockable contract; downstream files implement it.
|
|
@@ -17,20 +16,19 @@
|
|
|
17
16
|
*
|
|
18
17
|
* 2. `DetachHandle` — the consumer-facing handle returned by
|
|
19
18
|
* `detachAndJoinLater`. Exposes status as PROPERTIES (sync read)
|
|
20
|
-
* and `wait()` (Promise — opt-in async join).
|
|
21
|
-
* panel review: properties for sync, single method for async.
|
|
19
|
+
* and `wait()` (Promise — opt-in async join).
|
|
22
20
|
*
|
|
23
21
|
* Naming policy (locked from naming review):
|
|
24
22
|
* - Public API uses simple verbs / properties (product-engineer friendly)
|
|
25
23
|
* - Internal class names CAN use CS terms (Scheduler, Continuation, etc.)
|
|
26
24
|
* - Drivers are algorithm-named (semantic at the algorithm level)
|
|
27
25
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* -
|
|
31
|
-
* -
|
|
32
|
-
* -
|
|
33
|
-
* -
|
|
26
|
+
* Current lifecycle contract:
|
|
27
|
+
* - Return a handle synchronously; the selected driver owns dispatch
|
|
28
|
+
* - Scheduling/child errors → failed handle, never thrown to parent
|
|
29
|
+
* - `runChild.ts · defaultRunChild` uses an isolated child executor
|
|
30
|
+
* - `registry.ts` tracks in-flight handles for `flushAllDetached`
|
|
31
|
+
* - No automatic commit-log event or executor-disposal integration
|
|
34
32
|
* - Type-level rejection of `outputMapper` on detach options
|
|
35
33
|
*/
|
|
36
34
|
import type { FlowChart } from '../builder/types.js';
|
|
@@ -72,7 +70,8 @@ export interface DetachWaitResult {
|
|
|
72
70
|
* failed → terminal: error available
|
|
73
71
|
*
|
|
74
72
|
* `done` and `failed` are TERMINAL — once reached, status never
|
|
75
|
-
* changes again.
|
|
73
|
+
* changes again. A scheduling refusal can go straight from `queued`
|
|
74
|
+
* to `failed`, without starting the child.
|
|
76
75
|
*/
|
|
77
76
|
export interface DetachHandle {
|
|
78
77
|
/** Stable id assigned at detach time. Used as the lookup key in
|
|
@@ -150,8 +149,9 @@ export interface DriverCapabilities {
|
|
|
150
149
|
* never waits for the driver's deferred work to complete
|
|
151
150
|
*
|
|
152
151
|
* Drivers MAY:
|
|
153
|
-
* - Implement `validate()` for
|
|
154
|
-
*
|
|
152
|
+
* - Implement `validate()` for explicit caller-controlled preflight
|
|
153
|
+
* checks (e.g., assert `navigator.sendBeacon` exists). Scheduling
|
|
154
|
+
* must still contain failures when preflight was not requested.
|
|
155
155
|
* - Build their internal pipeline as a footprintjs flowChart for
|
|
156
156
|
* observability — driver implementation detail, not consumer-facing
|
|
157
157
|
*
|
|
@@ -184,17 +184,14 @@ export interface DetachDriver {
|
|
|
184
184
|
*/
|
|
185
185
|
schedule(child: FlowChart, input: unknown, refId: string): DetachHandle;
|
|
186
186
|
/**
|
|
187
|
-
* Optional
|
|
188
|
-
*
|
|
189
|
-
* configuration is invalid (
|
|
190
|
-
*
|
|
187
|
+
* Optional preflight hook, invoked explicitly by the caller, never
|
|
188
|
+
* automatically by the detach entry points. It may throw if the
|
|
189
|
+
* configuration is invalid. `schedule()` must independently report
|
|
190
|
+
* scheduling failures through its handle, even without preflight.
|
|
191
191
|
*
|
|
192
192
|
* Example: `sendBeaconDriver.validate()` checks
|
|
193
193
|
* `typeof navigator?.sendBeacon === 'function'` and throws with a
|
|
194
194
|
* helpful message if absent (e.g., in Node).
|
|
195
|
-
*
|
|
196
|
-
* Per the New Relic panel review: early-fail-with-useful-message
|
|
197
|
-
* beats silent zero-emission.
|
|
198
195
|
*/
|
|
199
196
|
validate?(): void;
|
|
200
197
|
}
|