brass-runtime 1.13.8 → 1.15.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/README.md +6 -3
- package/dist/agent/cli/main.cjs +44 -43
- package/dist/agent/cli/main.js +5 -4
- package/dist/agent/cli/main.mjs +5 -4
- package/dist/agent/index.cjs +4 -3
- package/dist/agent/index.d.ts +1 -1
- package/dist/agent/index.js +3 -2
- package/dist/agent/index.mjs +3 -2
- package/dist/{chunk-3R7ZYRK2.mjs → chunk-3QMOKAS5.js} +9 -7
- package/dist/{chunk-ATHSSDUF.js → chunk-4NHES7VK.mjs} +113 -31
- package/dist/chunk-AR22SXML.js +1043 -0
- package/dist/chunk-BDF4AMWX.mjs +3773 -0
- package/dist/chunk-BDYEENHT.js +224 -0
- package/dist/chunk-BMH5AV44.js +3773 -0
- package/dist/chunk-ELOOF35R.mjs +131 -0
- package/dist/chunk-JFPU5GQI.mjs +1043 -0
- package/dist/{chunk-INZBKOHY.js → chunk-K6M7MDZ4.mjs} +9 -7
- package/dist/chunk-MS34J5LY.cjs +224 -0
- package/dist/{chunk-XNOTJSMZ.mjs → chunk-PPUXIH5R.js} +113 -31
- package/dist/chunk-R3R2FVLG.cjs +131 -0
- package/dist/{chunk-ZTDK2DLG.cjs → chunk-STVLQ3XD.cjs} +169 -87
- package/dist/chunk-TGIFUAK4.cjs +3773 -0
- package/dist/chunk-TO7IKXYT.js +131 -0
- package/dist/chunk-UMAZLXAB.mjs +224 -0
- package/dist/{chunk-XDINDYNA.cjs → chunk-VEZNF5GZ.cjs} +136 -134
- package/dist/chunk-XPZNXSVN.cjs +1043 -0
- package/dist/core/index.cjs +216 -0
- package/dist/core/index.d.ts +673 -0
- package/dist/core/index.js +216 -0
- package/dist/core/index.mjs +216 -0
- package/dist/{effect-ISvXPLgc.d.ts → effect-CMOQKX8y.d.ts} +202 -31
- package/dist/http/index.cjs +3177 -187
- package/dist/http/index.d.ts +1692 -9
- package/dist/http/index.js +3164 -174
- package/dist/http/index.mjs +3164 -174
- package/dist/index.cjs +936 -219
- package/dist/index.d.ts +313 -36
- package/dist/index.js +830 -113
- package/dist/index.mjs +830 -113
- package/dist/{stream-BvukHxCv.d.ts → stream-FQm9h4Mg.d.ts} +12 -4
- package/dist/tracing-DNT9jEbr.d.ts +106 -0
- package/package.json +11 -3
- package/wasm/pkg/brass_runtime_wasm_engine.d.ts +95 -16
- package/wasm/pkg/brass_runtime_wasm_engine.js +715 -15
- package/wasm/pkg/brass_runtime_wasm_engine_bg.wasm +0 -0
- package/wasm/pkg/brass_runtime_wasm_engine_bg.wasm.d.ts +78 -7
- package/dist/chunk-2P4PD6D7.cjs +0 -2557
- package/dist/chunk-7F2R7A2V.mjs +0 -2557
- package/dist/chunk-L6KKKM66.js +0 -2557
package/dist/index.js
CHANGED
|
@@ -1,3 +1,54 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LinkedQueue,
|
|
3
|
+
andThen,
|
|
4
|
+
assertCompletesWithin,
|
|
5
|
+
assertFails,
|
|
6
|
+
assertFailsWith,
|
|
7
|
+
assertSucceeds,
|
|
8
|
+
bracket,
|
|
9
|
+
catchTag,
|
|
10
|
+
catchTags,
|
|
11
|
+
compose,
|
|
12
|
+
delayedEffect,
|
|
13
|
+
derivedRef,
|
|
14
|
+
elapsed,
|
|
15
|
+
ensuring,
|
|
16
|
+
exponential,
|
|
17
|
+
fixed,
|
|
18
|
+
flakyEffect,
|
|
19
|
+
gracefulShutdown,
|
|
20
|
+
intersect,
|
|
21
|
+
jittered,
|
|
22
|
+
layer,
|
|
23
|
+
layerFail,
|
|
24
|
+
layerFrom,
|
|
25
|
+
layerSucceed,
|
|
26
|
+
linkAbortController,
|
|
27
|
+
makeCancelToken,
|
|
28
|
+
makeMetrics,
|
|
29
|
+
makeRef,
|
|
30
|
+
makeSemaphore,
|
|
31
|
+
makeTestRuntime,
|
|
32
|
+
makeTracer,
|
|
33
|
+
makeWorkerPool,
|
|
34
|
+
managed,
|
|
35
|
+
managedAll,
|
|
36
|
+
mapError as mapError2,
|
|
37
|
+
mapLayer,
|
|
38
|
+
merge,
|
|
39
|
+
neverEffect,
|
|
40
|
+
orElse,
|
|
41
|
+
provideLayer,
|
|
42
|
+
recurs,
|
|
43
|
+
registerShutdownHooks,
|
|
44
|
+
repeatWithSchedule,
|
|
45
|
+
retryWithSchedule,
|
|
46
|
+
tagError,
|
|
47
|
+
take,
|
|
48
|
+
union,
|
|
49
|
+
useManaged,
|
|
50
|
+
whileInput
|
|
51
|
+
} from "./chunk-AR22SXML.js";
|
|
1
52
|
import {
|
|
2
53
|
assertNever,
|
|
3
54
|
collectStream,
|
|
@@ -10,7 +61,7 @@ import {
|
|
|
10
61
|
fromPull,
|
|
11
62
|
managedStream,
|
|
12
63
|
mapStream,
|
|
13
|
-
merge,
|
|
64
|
+
merge as merge2,
|
|
14
65
|
mergeStream,
|
|
15
66
|
rangeStream,
|
|
16
67
|
streamFromReadableStream,
|
|
@@ -18,19 +69,37 @@ import {
|
|
|
18
69
|
unwrapScoped,
|
|
19
70
|
widenOpt,
|
|
20
71
|
zip
|
|
21
|
-
} from "./chunk-
|
|
72
|
+
} from "./chunk-PPUXIH5R.js";
|
|
22
73
|
import {
|
|
74
|
+
makeCircuitBreaker,
|
|
75
|
+
retry,
|
|
76
|
+
retryN,
|
|
77
|
+
retryWithBackoff,
|
|
78
|
+
sleep,
|
|
79
|
+
timeout
|
|
80
|
+
} from "./chunk-BDYEENHT.js";
|
|
81
|
+
import {
|
|
82
|
+
collectAllPar,
|
|
83
|
+
race,
|
|
84
|
+
raceWith,
|
|
85
|
+
zipPar
|
|
86
|
+
} from "./chunk-TO7IKXYT.js";
|
|
87
|
+
import {
|
|
88
|
+
ABI_VERSION,
|
|
23
89
|
Async,
|
|
24
90
|
Cause,
|
|
25
91
|
DefaultHostExecutor,
|
|
92
|
+
EVENT_WORDS,
|
|
26
93
|
EngineFiberHandle,
|
|
94
|
+
EventKindCode,
|
|
27
95
|
Exit,
|
|
28
96
|
HostRegistry,
|
|
29
97
|
JsFiberEngine,
|
|
98
|
+
NONE_U32,
|
|
30
99
|
NoopHooks,
|
|
100
|
+
OpcodeTagCode,
|
|
31
101
|
ProgramBuilder,
|
|
32
102
|
PushStatus,
|
|
33
|
-
ReferenceWasmBridge,
|
|
34
103
|
RingBuffer,
|
|
35
104
|
Runtime,
|
|
36
105
|
RuntimeFiber,
|
|
@@ -39,9 +108,10 @@ import {
|
|
|
39
108
|
WasmFiberEngine,
|
|
40
109
|
WasmFiberRegistryBridge,
|
|
41
110
|
WasmPackFiberBridge,
|
|
111
|
+
abortablePromiseStats,
|
|
42
112
|
acquireRelease,
|
|
43
|
-
async,
|
|
44
113
|
asyncCatchAll,
|
|
114
|
+
asyncEffect,
|
|
45
115
|
asyncFail,
|
|
46
116
|
asyncFlatMap,
|
|
47
117
|
asyncFold,
|
|
@@ -52,7 +122,10 @@ import {
|
|
|
52
122
|
asyncSync,
|
|
53
123
|
asyncTotal,
|
|
54
124
|
catchAll,
|
|
55
|
-
|
|
125
|
+
decodeEvent,
|
|
126
|
+
decodeEventBatch,
|
|
127
|
+
encodeOpcodeNodes,
|
|
128
|
+
encodeOpcodeProgram,
|
|
56
129
|
end,
|
|
57
130
|
fail,
|
|
58
131
|
flatMap,
|
|
@@ -61,22 +134,27 @@ import {
|
|
|
61
134
|
getBenchmarkBudget,
|
|
62
135
|
getCurrentFiber,
|
|
63
136
|
globalScheduler,
|
|
137
|
+
inferCallerLaneFromStack,
|
|
138
|
+
laneTag,
|
|
64
139
|
makeBoundedRingBuffer,
|
|
140
|
+
makeFiberReadyQueue,
|
|
65
141
|
map,
|
|
66
142
|
mapAsync,
|
|
67
143
|
mapError,
|
|
68
144
|
mapTryAsync,
|
|
69
145
|
none,
|
|
70
146
|
orElseOptional,
|
|
71
|
-
|
|
72
|
-
raceWith,
|
|
147
|
+
resetAbortablePromiseStats,
|
|
73
148
|
resolveWasmModule,
|
|
74
149
|
runtimeCapabilities,
|
|
150
|
+
runtimeForCaller,
|
|
151
|
+
sanitizeLaneKey,
|
|
75
152
|
setBenchmarkBudget,
|
|
76
153
|
some,
|
|
77
154
|
succeed,
|
|
78
155
|
sync,
|
|
79
156
|
toPromise,
|
|
157
|
+
toPromiseByCaller,
|
|
80
158
|
unit,
|
|
81
159
|
unsafeGetCurrentRuntime,
|
|
82
160
|
unsafeRunAsync,
|
|
@@ -84,84 +162,8 @@ import {
|
|
|
84
162
|
withAsyncPromise,
|
|
85
163
|
withCurrentFiber,
|
|
86
164
|
withScope,
|
|
87
|
-
withScopeAsync
|
|
88
|
-
|
|
89
|
-
} from "./chunk-L6KKKM66.js";
|
|
90
|
-
|
|
91
|
-
// src/core/types/cancel.ts
|
|
92
|
-
function makeCancelToken() {
|
|
93
|
-
let cancelled = false;
|
|
94
|
-
const listeners = /* @__PURE__ */ new Set();
|
|
95
|
-
const cancel = () => {
|
|
96
|
-
if (cancelled) return;
|
|
97
|
-
cancelled = true;
|
|
98
|
-
listeners.forEach((f) => f());
|
|
99
|
-
listeners.clear();
|
|
100
|
-
};
|
|
101
|
-
return {
|
|
102
|
-
isCancelled: () => cancelled,
|
|
103
|
-
onCancel: (f) => {
|
|
104
|
-
if (cancelled) {
|
|
105
|
-
try {
|
|
106
|
-
f();
|
|
107
|
-
} catch {
|
|
108
|
-
}
|
|
109
|
-
return () => {
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
listeners.add(f);
|
|
113
|
-
return () => {
|
|
114
|
-
listeners.delete(f);
|
|
115
|
-
};
|
|
116
|
-
},
|
|
117
|
-
cancel
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
function linkAbortController(token, ac) {
|
|
121
|
-
return token.onCancel(() => ac.abort());
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// src/core/runtime/linkedQueue.ts
|
|
125
|
-
var LinkedQueue = class {
|
|
126
|
-
head = null;
|
|
127
|
-
tail = null;
|
|
128
|
-
len = 0;
|
|
129
|
-
get length() {
|
|
130
|
-
return this.len;
|
|
131
|
-
}
|
|
132
|
-
isEmpty() {
|
|
133
|
-
return this.len === 0;
|
|
134
|
-
}
|
|
135
|
-
push(value) {
|
|
136
|
-
const node = { value, next: null, prev: this.tail, removed: false };
|
|
137
|
-
if (this.tail) this.tail.next = node;
|
|
138
|
-
else this.head = node;
|
|
139
|
-
this.tail = node;
|
|
140
|
-
this.len++;
|
|
141
|
-
return node;
|
|
142
|
-
}
|
|
143
|
-
shift() {
|
|
144
|
-
const h = this.head;
|
|
145
|
-
if (!h) return void 0;
|
|
146
|
-
this.unlink(h);
|
|
147
|
-
return h.value;
|
|
148
|
-
}
|
|
149
|
-
remove(node) {
|
|
150
|
-
if (node.removed) return;
|
|
151
|
-
this.unlink(node);
|
|
152
|
-
}
|
|
153
|
-
unlink(node) {
|
|
154
|
-
node.removed = true;
|
|
155
|
-
const { prev, next } = node;
|
|
156
|
-
if (prev) prev.next = next;
|
|
157
|
-
else this.head = next;
|
|
158
|
-
if (next) next.prev = prev;
|
|
159
|
-
else this.tail = prev;
|
|
160
|
-
node.next = null;
|
|
161
|
-
node.prev = null;
|
|
162
|
-
this.len--;
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
+
withScopeAsync
|
|
166
|
+
} from "./chunk-BMH5AV44.js";
|
|
165
167
|
|
|
166
168
|
// src/core/stream/queue.ts
|
|
167
169
|
function bounded(capacity, strategy = "backpressure", options = {}) {
|
|
@@ -189,7 +191,7 @@ function makeQueue(capacity, strategy, options) {
|
|
|
189
191
|
return {
|
|
190
192
|
size: () => items.length,
|
|
191
193
|
shutdown,
|
|
192
|
-
offer: (a) =>
|
|
194
|
+
offer: (a) => asyncEffect((_env, cb) => {
|
|
193
195
|
if (closed) {
|
|
194
196
|
cb({ _tag: "Success", value: false });
|
|
195
197
|
return;
|
|
@@ -224,7 +226,7 @@ function makeQueue(capacity, strategy, options) {
|
|
|
224
226
|
};
|
|
225
227
|
return canceler;
|
|
226
228
|
}),
|
|
227
|
-
take: () =>
|
|
229
|
+
take: () => asyncEffect((_env, cb) => {
|
|
228
230
|
if (items.length > 0) {
|
|
229
231
|
const a = items.shift();
|
|
230
232
|
cb({ _tag: "Success", value: a });
|
|
@@ -250,6 +252,61 @@ function makeQueue(capacity, strategy, options) {
|
|
|
250
252
|
takers.remove(node);
|
|
251
253
|
};
|
|
252
254
|
return canceler;
|
|
255
|
+
}),
|
|
256
|
+
offerBatch: (values) => asyncSync(() => {
|
|
257
|
+
const results = [];
|
|
258
|
+
for (let i = 0; i < values.length; i++) {
|
|
259
|
+
if (closed) {
|
|
260
|
+
results.push(false);
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
const a = values[i];
|
|
264
|
+
if (takers.length > 0) {
|
|
265
|
+
const t = takers.shift();
|
|
266
|
+
t({ _tag: "Success", value: a });
|
|
267
|
+
results.push(true);
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
if (items.length < capacity) {
|
|
271
|
+
items.push(a);
|
|
272
|
+
results.push(true);
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
if (strategy === "dropping") {
|
|
276
|
+
results.push(false);
|
|
277
|
+
} else if (strategy === "sliding") {
|
|
278
|
+
items.shift();
|
|
279
|
+
items.push(a);
|
|
280
|
+
results.push(true);
|
|
281
|
+
} else {
|
|
282
|
+
results.push(false);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
return results;
|
|
286
|
+
}),
|
|
287
|
+
takeBatch: (n) => asyncSync(() => {
|
|
288
|
+
const results = [];
|
|
289
|
+
const count = Math.min(n, items.length + offerWaiters.length);
|
|
290
|
+
for (let i = 0; i < count; i++) {
|
|
291
|
+
if (items.length > 0) {
|
|
292
|
+
results.push(items.shift());
|
|
293
|
+
if (offerWaiters.length > 0 && items.length < capacity) {
|
|
294
|
+
const w = offerWaiters.shift();
|
|
295
|
+
items.push(w.a);
|
|
296
|
+
w.cb(true);
|
|
297
|
+
}
|
|
298
|
+
} else if (offerWaiters.length > 0) {
|
|
299
|
+
const w = offerWaiters.shift();
|
|
300
|
+
w.cb(true);
|
|
301
|
+
results.push(w.a);
|
|
302
|
+
} else {
|
|
303
|
+
break;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
if (results.length === 0 && closed) {
|
|
307
|
+
throw QueueClosedErr;
|
|
308
|
+
}
|
|
309
|
+
return results;
|
|
253
310
|
})
|
|
254
311
|
};
|
|
255
312
|
}
|
|
@@ -431,14 +488,12 @@ function resolveWasmChunkBuffer() {
|
|
|
431
488
|
cachedWasmChunkCtor = mod?.BrassWasmChunkBuffer ?? null;
|
|
432
489
|
return cachedWasmChunkCtor;
|
|
433
490
|
}
|
|
434
|
-
var
|
|
435
|
-
constructor(maxChunkSize
|
|
491
|
+
var TsChunker = class {
|
|
492
|
+
constructor(maxChunkSize) {
|
|
436
493
|
this.maxChunkSize = maxChunkSize;
|
|
437
|
-
this.fallbackUsed = fallbackUsed;
|
|
438
494
|
}
|
|
439
495
|
maxChunkSize;
|
|
440
|
-
|
|
441
|
-
engine = "js";
|
|
496
|
+
engine = "ts";
|
|
442
497
|
values = [];
|
|
443
498
|
emittedChunks = 0;
|
|
444
499
|
emittedItems = 0;
|
|
@@ -472,8 +527,8 @@ var JsChunker = class {
|
|
|
472
527
|
}
|
|
473
528
|
stats() {
|
|
474
529
|
return {
|
|
475
|
-
engine: "
|
|
476
|
-
fallbackUsed:
|
|
530
|
+
engine: "ts",
|
|
531
|
+
fallbackUsed: false,
|
|
477
532
|
data: {
|
|
478
533
|
len: this.values.length,
|
|
479
534
|
maxChunkSize: this.maxChunkSize,
|
|
@@ -522,10 +577,10 @@ var WasmChunker = class {
|
|
|
522
577
|
};
|
|
523
578
|
function makeStreamChunker(chunkSize, options = {}) {
|
|
524
579
|
const size = Math.max(1, chunkSize | 0);
|
|
525
|
-
const engine = options.engine ?? "
|
|
526
|
-
if (engine === "
|
|
580
|
+
const engine = options.engine ?? "ts";
|
|
581
|
+
if (engine === "ts") return new TsChunker(size);
|
|
527
582
|
if (engine === "wasm") return new WasmChunker(size);
|
|
528
|
-
|
|
583
|
+
throw new Error(`brass-runtime stream chunk engine must be 'ts' or 'wasm'; received '${String(engine)}'`);
|
|
529
584
|
}
|
|
530
585
|
function chunks(input, chunkSize, options = {}) {
|
|
531
586
|
const size = Math.max(1, chunkSize | 0);
|
|
@@ -591,21 +646,430 @@ function mapChunksEffect(chunkSize, f, options = {}) {
|
|
|
591
646
|
});
|
|
592
647
|
}
|
|
593
648
|
|
|
649
|
+
// src/core/stream/fusion.ts
|
|
650
|
+
var _fusionEnabled = true;
|
|
651
|
+
var _fusionVerbose = false;
|
|
652
|
+
function setFusionEnabled(enabled) {
|
|
653
|
+
_fusionEnabled = enabled;
|
|
654
|
+
}
|
|
655
|
+
function isFusionEnabled() {
|
|
656
|
+
return _fusionEnabled;
|
|
657
|
+
}
|
|
658
|
+
function setFusionVerbose(verbose) {
|
|
659
|
+
_fusionVerbose = verbose;
|
|
660
|
+
}
|
|
661
|
+
function isFusionVerbose() {
|
|
662
|
+
return _fusionVerbose;
|
|
663
|
+
}
|
|
664
|
+
function getStats(pipeline) {
|
|
665
|
+
const p = pipeline;
|
|
666
|
+
if (p._fusedSteps && Array.isArray(p._fusedSteps)) {
|
|
667
|
+
const metas = p._fusedSteps;
|
|
668
|
+
return buildStats(metas);
|
|
669
|
+
}
|
|
670
|
+
if (p[PURE_PIPELINE_TAG]) {
|
|
671
|
+
return null;
|
|
672
|
+
}
|
|
673
|
+
return null;
|
|
674
|
+
}
|
|
675
|
+
var PURE_PIPELINE_TAG = /* @__PURE__ */ Symbol("brass:pure-pipeline");
|
|
676
|
+
function makeMapStep(fn) {
|
|
677
|
+
return (a, _state) => ({ tag: "emit", value: fn(a) });
|
|
678
|
+
}
|
|
679
|
+
function makeFilterStep(pred) {
|
|
680
|
+
return (a, _state) => pred(a) ? { tag: "emit", value: a } : { tag: "skip" };
|
|
681
|
+
}
|
|
682
|
+
function makeTakeStep(n, counterIndex) {
|
|
683
|
+
return (a, state) => {
|
|
684
|
+
if (state.counters[counterIndex] >= n) {
|
|
685
|
+
return { tag: "halt" };
|
|
686
|
+
}
|
|
687
|
+
state.counters[counterIndex]++;
|
|
688
|
+
return { tag: "emit", value: a };
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
function makeDropStep(n, counterIndex) {
|
|
692
|
+
return (a, state) => {
|
|
693
|
+
if (state.counters[counterIndex] < n) {
|
|
694
|
+
state.counters[counterIndex]++;
|
|
695
|
+
return { tag: "skip" };
|
|
696
|
+
}
|
|
697
|
+
return { tag: "emit", value: a };
|
|
698
|
+
};
|
|
699
|
+
}
|
|
700
|
+
function initState(counterCount) {
|
|
701
|
+
return () => ({
|
|
702
|
+
counters: new Array(counterCount).fill(0)
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
function composeSteps(step1, step2) {
|
|
706
|
+
return (a, state) => {
|
|
707
|
+
const r1 = step1(a, state);
|
|
708
|
+
if (r1.tag !== "emit") return r1;
|
|
709
|
+
return step2(r1.value, state);
|
|
710
|
+
};
|
|
711
|
+
}
|
|
712
|
+
function getPureTag(pipeline) {
|
|
713
|
+
const tagged = pipeline;
|
|
714
|
+
return tagged[PURE_PIPELINE_TAG] ?? null;
|
|
715
|
+
}
|
|
716
|
+
function getFusedSteps(pipeline) {
|
|
717
|
+
const p = pipeline;
|
|
718
|
+
if (p._fusedSteps && Array.isArray(p._fusedSteps)) {
|
|
719
|
+
return p._fusedSteps;
|
|
720
|
+
}
|
|
721
|
+
return null;
|
|
722
|
+
}
|
|
723
|
+
function buildStepFromMetadata(meta, counterIndex) {
|
|
724
|
+
switch (meta.kind) {
|
|
725
|
+
case "map":
|
|
726
|
+
return makeMapStep(meta.fn);
|
|
727
|
+
case "filter":
|
|
728
|
+
return makeFilterStep(meta.pred);
|
|
729
|
+
case "take":
|
|
730
|
+
return makeTakeStep(meta.n, counterIndex);
|
|
731
|
+
case "drop":
|
|
732
|
+
return makeDropStep(meta.n, counterIndex);
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
function buildStats(metas) {
|
|
736
|
+
const steps = metas.map((m) => {
|
|
737
|
+
switch (m.kind) {
|
|
738
|
+
case "map":
|
|
739
|
+
return { kind: "map" };
|
|
740
|
+
case "filter":
|
|
741
|
+
return { kind: "filter" };
|
|
742
|
+
case "take":
|
|
743
|
+
return { kind: "take", n: m.n };
|
|
744
|
+
case "drop":
|
|
745
|
+
return { kind: "drop", n: m.n };
|
|
746
|
+
}
|
|
747
|
+
});
|
|
748
|
+
return {
|
|
749
|
+
fusedSteps: steps.length,
|
|
750
|
+
steps,
|
|
751
|
+
hasTake: metas.some((m) => m.kind === "take"),
|
|
752
|
+
hasDrop: metas.some((m) => m.kind === "drop")
|
|
753
|
+
};
|
|
754
|
+
}
|
|
755
|
+
function countCounters(metas) {
|
|
756
|
+
let count = 0;
|
|
757
|
+
for (const m of metas) {
|
|
758
|
+
if (m.kind === "take" || m.kind === "drop") {
|
|
759
|
+
count++;
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
return count;
|
|
763
|
+
}
|
|
764
|
+
function fuse(pipeline, options) {
|
|
765
|
+
const verbose = options?.verbose ?? _fusionVerbose;
|
|
766
|
+
if (options?.enabled === false || !_fusionEnabled && options?.enabled !== true) {
|
|
767
|
+
if (verbose) {
|
|
768
|
+
console.log("[FusionEngine] Fusion disabled by options");
|
|
769
|
+
}
|
|
770
|
+
return null;
|
|
771
|
+
}
|
|
772
|
+
const metas = collectMetadata(pipeline);
|
|
773
|
+
if (!metas || metas.length === 0) {
|
|
774
|
+
if (verbose) {
|
|
775
|
+
console.log("[FusionEngine] Pipeline is not fusable (no pure tags detected)");
|
|
776
|
+
}
|
|
777
|
+
return null;
|
|
778
|
+
}
|
|
779
|
+
if (verbose) {
|
|
780
|
+
console.log(
|
|
781
|
+
`[FusionEngine] Fusing ${metas.length} steps: ${metas.map((m) => m.kind).join(" \u2192 ")}`
|
|
782
|
+
);
|
|
783
|
+
}
|
|
784
|
+
let counterIndex = 0;
|
|
785
|
+
let composedStep = buildStepFromMetadata(
|
|
786
|
+
metas[0],
|
|
787
|
+
metas[0].kind === "take" || metas[0].kind === "drop" ? counterIndex++ : -1
|
|
788
|
+
);
|
|
789
|
+
for (let i = 1; i < metas.length; i++) {
|
|
790
|
+
const meta = metas[i];
|
|
791
|
+
const idx = meta.kind === "take" || meta.kind === "drop" ? counterIndex++ : -1;
|
|
792
|
+
composedStep = composeSteps(composedStep, buildStepFromMetadata(meta, idx));
|
|
793
|
+
}
|
|
794
|
+
const counterCount = countCounters(metas);
|
|
795
|
+
const stats = buildStats(metas);
|
|
796
|
+
return {
|
|
797
|
+
_tag: "FusedPipeline",
|
|
798
|
+
step: composedStep,
|
|
799
|
+
initState: initState(counterCount),
|
|
800
|
+
stats
|
|
801
|
+
};
|
|
802
|
+
}
|
|
803
|
+
function collectMetadata(pipeline) {
|
|
804
|
+
const fusedSteps = getFusedSteps(pipeline);
|
|
805
|
+
if (fusedSteps) {
|
|
806
|
+
return fusedSteps;
|
|
807
|
+
}
|
|
808
|
+
const tag = getPureTag(pipeline);
|
|
809
|
+
if (tag) {
|
|
810
|
+
return [tag];
|
|
811
|
+
}
|
|
812
|
+
return null;
|
|
813
|
+
}
|
|
814
|
+
function runFusedArray(input, fused) {
|
|
815
|
+
const state = fused.initState();
|
|
816
|
+
const output = [];
|
|
817
|
+
for (let i = 0; i < input.length; i++) {
|
|
818
|
+
const result = fused.step(input[i], state);
|
|
819
|
+
switch (result.tag) {
|
|
820
|
+
case "emit":
|
|
821
|
+
output.push(result.value);
|
|
822
|
+
break;
|
|
823
|
+
case "skip":
|
|
824
|
+
break;
|
|
825
|
+
case "halt":
|
|
826
|
+
return output;
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
return output;
|
|
830
|
+
}
|
|
831
|
+
function drainStreamSync(stream) {
|
|
832
|
+
const result = [];
|
|
833
|
+
let cur = stream;
|
|
834
|
+
while (true) {
|
|
835
|
+
switch (cur._tag) {
|
|
836
|
+
case "Empty":
|
|
837
|
+
return result;
|
|
838
|
+
case "FromArray": {
|
|
839
|
+
const arr = cur.values;
|
|
840
|
+
for (let i = 0; i < arr.length; i++) {
|
|
841
|
+
result.push(arr[i]);
|
|
842
|
+
}
|
|
843
|
+
return result;
|
|
844
|
+
}
|
|
845
|
+
case "Emit": {
|
|
846
|
+
const zio = cur.value;
|
|
847
|
+
if (zio._tag === "Succeed") {
|
|
848
|
+
result.push(zio.value);
|
|
849
|
+
return result;
|
|
850
|
+
}
|
|
851
|
+
return null;
|
|
852
|
+
}
|
|
853
|
+
case "Concat": {
|
|
854
|
+
const leftItems = drainStreamSync(cur.left);
|
|
855
|
+
if (leftItems === null) return null;
|
|
856
|
+
for (let i = 0; i < leftItems.length; i++) {
|
|
857
|
+
result.push(leftItems[i]);
|
|
858
|
+
}
|
|
859
|
+
cur = cur.right;
|
|
860
|
+
break;
|
|
861
|
+
}
|
|
862
|
+
default:
|
|
863
|
+
return null;
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
function applyFused(stream, fused) {
|
|
868
|
+
const inputArray = drainStreamSync(stream);
|
|
869
|
+
if (inputArray !== null) {
|
|
870
|
+
const outputArray = runFusedArray(inputArray, fused);
|
|
871
|
+
return arrayToStream(outputArray);
|
|
872
|
+
}
|
|
873
|
+
const state = fused.initState();
|
|
874
|
+
const loop = (cur) => fromPull(
|
|
875
|
+
asyncFold(
|
|
876
|
+
uncons(cur),
|
|
877
|
+
// End-of-stream or error: propagate
|
|
878
|
+
(opt) => asyncFail(opt),
|
|
879
|
+
([a, tail]) => {
|
|
880
|
+
const result = fused.step(a, state);
|
|
881
|
+
switch (result.tag) {
|
|
882
|
+
case "emit":
|
|
883
|
+
return asyncSucceed([result.value, loop(tail)]);
|
|
884
|
+
case "skip":
|
|
885
|
+
return uncons(loop(tail));
|
|
886
|
+
case "halt":
|
|
887
|
+
return asyncFail(none);
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
)
|
|
891
|
+
);
|
|
892
|
+
return loop(stream);
|
|
893
|
+
}
|
|
894
|
+
function arrayToStream(values) {
|
|
895
|
+
if (values.length === 0) return { _tag: "Empty" };
|
|
896
|
+
return { _tag: "FromArray", values };
|
|
897
|
+
}
|
|
898
|
+
function serializeFusedPipeline(pipeline) {
|
|
899
|
+
const p = pipeline;
|
|
900
|
+
let metas = null;
|
|
901
|
+
if (p._fusedSteps && Array.isArray(p._fusedSteps)) {
|
|
902
|
+
metas = p._fusedSteps;
|
|
903
|
+
} else if (p[PURE_PIPELINE_TAG]) {
|
|
904
|
+
return null;
|
|
905
|
+
}
|
|
906
|
+
if (!metas || metas.length === 0) {
|
|
907
|
+
return null;
|
|
908
|
+
}
|
|
909
|
+
const steps = metas.map((meta) => {
|
|
910
|
+
switch (meta.kind) {
|
|
911
|
+
case "map":
|
|
912
|
+
return { kind: "map", fnSource: meta.fn.toString() };
|
|
913
|
+
case "filter":
|
|
914
|
+
return { kind: "filter", predSource: meta.pred.toString() };
|
|
915
|
+
case "take":
|
|
916
|
+
return { kind: "take", n: meta.n };
|
|
917
|
+
case "drop":
|
|
918
|
+
return { kind: "drop", n: meta.n };
|
|
919
|
+
}
|
|
920
|
+
});
|
|
921
|
+
return { version: 1, steps };
|
|
922
|
+
}
|
|
923
|
+
function deserializeFusedPipeline(serialized) {
|
|
924
|
+
try {
|
|
925
|
+
if (serialized.version !== 1) {
|
|
926
|
+
return null;
|
|
927
|
+
}
|
|
928
|
+
if (!serialized.steps || serialized.steps.length === 0) {
|
|
929
|
+
return null;
|
|
930
|
+
}
|
|
931
|
+
const metas = [];
|
|
932
|
+
for (const step of serialized.steps) {
|
|
933
|
+
switch (step.kind) {
|
|
934
|
+
case "map": {
|
|
935
|
+
const fn = new Function("return " + step.fnSource)();
|
|
936
|
+
if (typeof fn !== "function") return null;
|
|
937
|
+
metas.push({ kind: "map", fn });
|
|
938
|
+
break;
|
|
939
|
+
}
|
|
940
|
+
case "filter": {
|
|
941
|
+
const pred = new Function("return " + step.predSource)();
|
|
942
|
+
if (typeof pred !== "function") return null;
|
|
943
|
+
metas.push({ kind: "filter", pred });
|
|
944
|
+
break;
|
|
945
|
+
}
|
|
946
|
+
case "take": {
|
|
947
|
+
if (typeof step.n !== "number" || step.n < 0) return null;
|
|
948
|
+
metas.push({ kind: "take", n: step.n });
|
|
949
|
+
break;
|
|
950
|
+
}
|
|
951
|
+
case "drop": {
|
|
952
|
+
if (typeof step.n !== "number" || step.n < 0) return null;
|
|
953
|
+
metas.push({ kind: "drop", n: step.n });
|
|
954
|
+
break;
|
|
955
|
+
}
|
|
956
|
+
default:
|
|
957
|
+
return null;
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
const carrier = createDeserializedCarrier(metas);
|
|
961
|
+
return carrier;
|
|
962
|
+
} catch {
|
|
963
|
+
return null;
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
function createDeserializedCarrier(metas) {
|
|
967
|
+
let counterIndex = 0;
|
|
968
|
+
let composedStep = buildStepFromMetadata(
|
|
969
|
+
metas[0],
|
|
970
|
+
metas[0].kind === "take" || metas[0].kind === "drop" ? counterIndex++ : -1
|
|
971
|
+
);
|
|
972
|
+
for (let i = 1; i < metas.length; i++) {
|
|
973
|
+
const meta = metas[i];
|
|
974
|
+
const idx = meta.kind === "take" || meta.kind === "drop" ? counterIndex++ : -1;
|
|
975
|
+
composedStep = composeSteps(composedStep, buildStepFromMetadata(meta, idx));
|
|
976
|
+
}
|
|
977
|
+
const counterCount = countCounters(metas);
|
|
978
|
+
const stats = buildStats(metas);
|
|
979
|
+
const fusedRepr = {
|
|
980
|
+
_tag: "FusedPipeline",
|
|
981
|
+
step: composedStep,
|
|
982
|
+
initState: initState(counterCount),
|
|
983
|
+
stats
|
|
984
|
+
};
|
|
985
|
+
const pipeline = ((input) => {
|
|
986
|
+
return applyFused(input, fusedRepr);
|
|
987
|
+
});
|
|
988
|
+
pipeline._fusedSteps = metas;
|
|
989
|
+
return pipeline;
|
|
990
|
+
}
|
|
991
|
+
|
|
594
992
|
// src/core/stream/pipeline.ts
|
|
595
993
|
function via(stream, pipeline) {
|
|
994
|
+
if (isFusionEnabled()) {
|
|
995
|
+
const p = pipeline;
|
|
996
|
+
if (p._fusedSteps || p[PURE_PIPELINE_TAG]) {
|
|
997
|
+
let fusedRepr = p._cachedFusedRepr;
|
|
998
|
+
if (!fusedRepr) {
|
|
999
|
+
fusedRepr = fuse(pipeline);
|
|
1000
|
+
if (fusedRepr) p._cachedFusedRepr = fusedRepr;
|
|
1001
|
+
}
|
|
1002
|
+
if (fusedRepr) {
|
|
1003
|
+
return applyFused(stream, fusedRepr);
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
596
1007
|
return pipeline(stream);
|
|
597
1008
|
}
|
|
598
|
-
function
|
|
1009
|
+
function andThen2(p1, p2) {
|
|
1010
|
+
const fused = tryFuse(p1, p2);
|
|
1011
|
+
if (fused) return fused;
|
|
599
1012
|
return ((input) => p2(p1(input)));
|
|
600
1013
|
}
|
|
601
|
-
function
|
|
602
|
-
|
|
1014
|
+
function collectPureMetas(pipeline) {
|
|
1015
|
+
const p = pipeline;
|
|
1016
|
+
if (p._fusedSteps && Array.isArray(p._fusedSteps)) {
|
|
1017
|
+
return p._fusedSteps;
|
|
1018
|
+
}
|
|
1019
|
+
const tag = p[PURE_PIPELINE_TAG];
|
|
1020
|
+
if (tag) {
|
|
1021
|
+
return [tag];
|
|
1022
|
+
}
|
|
1023
|
+
return null;
|
|
1024
|
+
}
|
|
1025
|
+
function tryFuse(p1, p2) {
|
|
1026
|
+
if (!isFusionEnabled()) {
|
|
1027
|
+
if (isFusionVerbose()) {
|
|
1028
|
+
console.log("[FusionEngine] andThen: fusion globally disabled, skipping");
|
|
1029
|
+
}
|
|
1030
|
+
return null;
|
|
1031
|
+
}
|
|
1032
|
+
const metas1 = collectPureMetas(p1);
|
|
1033
|
+
const metas2 = collectPureMetas(p2);
|
|
1034
|
+
if (!metas1 || !metas2) {
|
|
1035
|
+
if (isFusionVerbose()) {
|
|
1036
|
+
const reason = !metas1 && !metas2 ? "neither operand is pure" : !metas1 ? "left operand is not pure" : "right operand is not pure";
|
|
1037
|
+
console.log(`[FusionEngine] andThen: cannot fuse \u2014 ${reason}`);
|
|
1038
|
+
}
|
|
1039
|
+
return null;
|
|
1040
|
+
}
|
|
1041
|
+
const combinedMetas = [...metas1, ...metas2];
|
|
1042
|
+
const fusedRepr = fuse(
|
|
1043
|
+
createMetadataCarrier(combinedMetas)
|
|
1044
|
+
);
|
|
1045
|
+
if (!fusedRepr) {
|
|
1046
|
+
return null;
|
|
1047
|
+
}
|
|
1048
|
+
if (isFusionVerbose()) {
|
|
1049
|
+
console.log(
|
|
1050
|
+
`[FusionEngine] andThen: fused ${combinedMetas.length} steps: ${combinedMetas.map((m) => m.kind).join(" \u2192 ")}`
|
|
1051
|
+
);
|
|
1052
|
+
}
|
|
1053
|
+
const fusedPipeline = ((input) => {
|
|
1054
|
+
return applyFused(input, fusedRepr);
|
|
1055
|
+
});
|
|
1056
|
+
fusedPipeline._fusedSteps = combinedMetas;
|
|
1057
|
+
return fusedPipeline;
|
|
1058
|
+
}
|
|
1059
|
+
function createMetadataCarrier(metas) {
|
|
1060
|
+
const carrier = (() => {
|
|
1061
|
+
});
|
|
1062
|
+
carrier._fusedSteps = metas;
|
|
1063
|
+
return carrier;
|
|
1064
|
+
}
|
|
1065
|
+
function compose2(p2, p1) {
|
|
1066
|
+
return andThen2(p1, p2);
|
|
603
1067
|
}
|
|
604
1068
|
function identity() {
|
|
605
1069
|
return ((input) => input);
|
|
606
1070
|
}
|
|
607
1071
|
function mapP(f) {
|
|
608
|
-
|
|
1072
|
+
const pipeline = ((input) => {
|
|
609
1073
|
const onError = (opt) => asyncFail(opt);
|
|
610
1074
|
const onSuccess = ([a, tail]) => asyncSucceed([f(a), loop(tail)]);
|
|
611
1075
|
const loop = (cur) => fromPull(
|
|
@@ -613,15 +1077,19 @@ function mapP(f) {
|
|
|
613
1077
|
);
|
|
614
1078
|
return loop(input);
|
|
615
1079
|
});
|
|
1080
|
+
pipeline[PURE_PIPELINE_TAG] = { kind: "map", fn: f };
|
|
1081
|
+
return pipeline;
|
|
616
1082
|
}
|
|
617
1083
|
function filterP(pred) {
|
|
618
|
-
|
|
1084
|
+
const pipeline = ((input) => {
|
|
619
1085
|
const onError = (opt) => asyncFail(opt);
|
|
620
1086
|
const onSuccess = ([a, tail]) => pred(a) ? asyncSucceed([a, loop(tail)]) : next(tail);
|
|
621
1087
|
const next = (cur) => asyncFold(uncons(cur), onError, onSuccess);
|
|
622
1088
|
const loop = (cur) => fromPull(next(cur));
|
|
623
1089
|
return loop(input);
|
|
624
1090
|
});
|
|
1091
|
+
pipeline[PURE_PIPELINE_TAG] = { kind: "filter", pred };
|
|
1092
|
+
return pipeline;
|
|
625
1093
|
}
|
|
626
1094
|
function filterMapP(f) {
|
|
627
1095
|
return ((input) => {
|
|
@@ -640,7 +1108,7 @@ function filterMapP(f) {
|
|
|
640
1108
|
}
|
|
641
1109
|
function takeP(n) {
|
|
642
1110
|
const m = Math.max(0, n | 0);
|
|
643
|
-
|
|
1111
|
+
const pipeline = ((input) => {
|
|
644
1112
|
const loop = (cur, remaining) => {
|
|
645
1113
|
if (remaining <= 0) return emptyStream();
|
|
646
1114
|
return fromPull(
|
|
@@ -653,10 +1121,12 @@ function takeP(n) {
|
|
|
653
1121
|
};
|
|
654
1122
|
return loop(input, m);
|
|
655
1123
|
});
|
|
1124
|
+
pipeline[PURE_PIPELINE_TAG] = { kind: "take", n: m };
|
|
1125
|
+
return pipeline;
|
|
656
1126
|
}
|
|
657
1127
|
function dropP(n) {
|
|
658
1128
|
const m = Math.max(0, n | 0);
|
|
659
|
-
|
|
1129
|
+
const pipeline = ((input) => {
|
|
660
1130
|
const skip = (cur, remaining) => {
|
|
661
1131
|
if (remaining <= 0) return cur;
|
|
662
1132
|
return fromPull(
|
|
@@ -669,6 +1139,8 @@ function dropP(n) {
|
|
|
669
1139
|
};
|
|
670
1140
|
return skip(input, m);
|
|
671
1141
|
});
|
|
1142
|
+
pipeline[PURE_PIPELINE_TAG] = { kind: "drop", n: m };
|
|
1143
|
+
return pipeline;
|
|
672
1144
|
}
|
|
673
1145
|
function mapEffectP(f) {
|
|
674
1146
|
return ((input) => {
|
|
@@ -731,25 +1203,187 @@ function groupedP(n) {
|
|
|
731
1203
|
});
|
|
732
1204
|
}
|
|
733
1205
|
|
|
1206
|
+
// src/core/stream/operators.ts
|
|
1207
|
+
function throttle(stream, intervalMs) {
|
|
1208
|
+
let lastEmitTime = 0;
|
|
1209
|
+
const loop = (cur) => fromPull(
|
|
1210
|
+
asyncFold(
|
|
1211
|
+
uncons(cur),
|
|
1212
|
+
(opt) => asyncFail(opt),
|
|
1213
|
+
([a, tail]) => {
|
|
1214
|
+
const now = Date.now();
|
|
1215
|
+
if (now - lastEmitTime >= intervalMs) {
|
|
1216
|
+
lastEmitTime = now;
|
|
1217
|
+
return asyncSucceed([a, loop(tail)]);
|
|
1218
|
+
}
|
|
1219
|
+
return uncons(loop(tail));
|
|
1220
|
+
}
|
|
1221
|
+
)
|
|
1222
|
+
);
|
|
1223
|
+
return loop(stream);
|
|
1224
|
+
}
|
|
1225
|
+
function debounce(stream, delayMs) {
|
|
1226
|
+
return fromPull(
|
|
1227
|
+
asyncEffect((_env, cb) => {
|
|
1228
|
+
let lastValue;
|
|
1229
|
+
let hasValue = false;
|
|
1230
|
+
let timerId;
|
|
1231
|
+
let done = false;
|
|
1232
|
+
let tail = stream;
|
|
1233
|
+
const pullNext = () => {
|
|
1234
|
+
if (done) return;
|
|
1235
|
+
const pull = uncons(tail);
|
|
1236
|
+
unsafeRunAsync(pull, _env, (exit) => {
|
|
1237
|
+
if (done) return;
|
|
1238
|
+
if (exit._tag === "Failure") {
|
|
1239
|
+
if (hasValue) {
|
|
1240
|
+
const value = lastValue;
|
|
1241
|
+
hasValue = false;
|
|
1242
|
+
clearTimeout(timerId);
|
|
1243
|
+
cb({ _tag: "Success", value: [value, emptyStream()] });
|
|
1244
|
+
} else {
|
|
1245
|
+
cb(exit);
|
|
1246
|
+
}
|
|
1247
|
+
return;
|
|
1248
|
+
}
|
|
1249
|
+
const [a, nextTail] = exit.value;
|
|
1250
|
+
tail = nextTail;
|
|
1251
|
+
lastValue = a;
|
|
1252
|
+
hasValue = true;
|
|
1253
|
+
clearTimeout(timerId);
|
|
1254
|
+
timerId = setTimeout(() => {
|
|
1255
|
+
if (done) return;
|
|
1256
|
+
const value = lastValue;
|
|
1257
|
+
hasValue = false;
|
|
1258
|
+
done = true;
|
|
1259
|
+
cb({ _tag: "Success", value: [value, debounce(tail, delayMs)] });
|
|
1260
|
+
}, delayMs);
|
|
1261
|
+
pullNext();
|
|
1262
|
+
});
|
|
1263
|
+
};
|
|
1264
|
+
pullNext();
|
|
1265
|
+
return () => {
|
|
1266
|
+
done = true;
|
|
1267
|
+
clearTimeout(timerId);
|
|
1268
|
+
};
|
|
1269
|
+
})
|
|
1270
|
+
);
|
|
1271
|
+
}
|
|
1272
|
+
function zip2(left, right) {
|
|
1273
|
+
const loop = (l, r) => fromPull(
|
|
1274
|
+
asyncFold(
|
|
1275
|
+
uncons(l),
|
|
1276
|
+
(opt) => asyncFail(opt),
|
|
1277
|
+
([a, lTail]) => asyncFold(
|
|
1278
|
+
uncons(r),
|
|
1279
|
+
(opt) => asyncFail(opt),
|
|
1280
|
+
([b, rTail]) => asyncSucceed([[a, b], loop(lTail, rTail)])
|
|
1281
|
+
)
|
|
1282
|
+
)
|
|
1283
|
+
);
|
|
1284
|
+
return loop(left, right);
|
|
1285
|
+
}
|
|
1286
|
+
function zipWith(left, right, f) {
|
|
1287
|
+
const loop = (l, r) => fromPull(
|
|
1288
|
+
asyncFold(
|
|
1289
|
+
uncons(l),
|
|
1290
|
+
(opt) => asyncFail(opt),
|
|
1291
|
+
([a, lTail]) => asyncFold(
|
|
1292
|
+
uncons(r),
|
|
1293
|
+
(opt) => asyncFail(opt),
|
|
1294
|
+
([b, rTail]) => asyncSucceed([f(a, b), loop(lTail, rTail)])
|
|
1295
|
+
)
|
|
1296
|
+
)
|
|
1297
|
+
);
|
|
1298
|
+
return loop(left, right);
|
|
1299
|
+
}
|
|
1300
|
+
function scan(stream, initial, f) {
|
|
1301
|
+
const loop = (cur, acc) => fromPull(
|
|
1302
|
+
asyncFold(
|
|
1303
|
+
uncons(cur),
|
|
1304
|
+
(opt) => asyncFail(opt),
|
|
1305
|
+
([a, tail]) => {
|
|
1306
|
+
const next = f(acc, a);
|
|
1307
|
+
return asyncSucceed([next, loop(tail, next)]);
|
|
1308
|
+
}
|
|
1309
|
+
)
|
|
1310
|
+
);
|
|
1311
|
+
return concatStream(
|
|
1312
|
+
emitStream(succeed(initial)),
|
|
1313
|
+
loop(stream, initial)
|
|
1314
|
+
);
|
|
1315
|
+
}
|
|
1316
|
+
function interleave(left, right) {
|
|
1317
|
+
const loop = (l, r, pickLeft) => fromPull(
|
|
1318
|
+
asyncFold(
|
|
1319
|
+
uncons(pickLeft ? l : r),
|
|
1320
|
+
// Current stream ended — drain the other
|
|
1321
|
+
(_opt) => uncons(pickLeft ? r : l),
|
|
1322
|
+
([a, tail]) => {
|
|
1323
|
+
const nextL = pickLeft ? tail : l;
|
|
1324
|
+
const nextR = pickLeft ? r : tail;
|
|
1325
|
+
return asyncSucceed([a, loop(nextL, nextR, !pickLeft)]);
|
|
1326
|
+
}
|
|
1327
|
+
)
|
|
1328
|
+
);
|
|
1329
|
+
return loop(left, right, true);
|
|
1330
|
+
}
|
|
1331
|
+
function take2(stream, n) {
|
|
1332
|
+
if (n <= 0) return emptyStream();
|
|
1333
|
+
const loop = (cur, remaining) => {
|
|
1334
|
+
if (remaining <= 0) return emptyStream();
|
|
1335
|
+
return fromPull(
|
|
1336
|
+
asyncFold(
|
|
1337
|
+
uncons(cur),
|
|
1338
|
+
(opt) => asyncFail(opt),
|
|
1339
|
+
([a, tail]) => asyncSucceed([a, loop(tail, remaining - 1)])
|
|
1340
|
+
)
|
|
1341
|
+
);
|
|
1342
|
+
};
|
|
1343
|
+
return loop(stream, n);
|
|
1344
|
+
}
|
|
1345
|
+
function drop(stream, n) {
|
|
1346
|
+
if (n <= 0) return stream;
|
|
1347
|
+
const skip = (cur, remaining) => {
|
|
1348
|
+
if (remaining <= 0) return cur;
|
|
1349
|
+
return fromPull(
|
|
1350
|
+
asyncFold(
|
|
1351
|
+
uncons(cur),
|
|
1352
|
+
(opt) => asyncFail(opt),
|
|
1353
|
+
([_a, tail]) => uncons(skip(tail, remaining - 1))
|
|
1354
|
+
)
|
|
1355
|
+
);
|
|
1356
|
+
};
|
|
1357
|
+
return skip(stream, n);
|
|
1358
|
+
}
|
|
1359
|
+
|
|
734
1360
|
// src/core/runtime/engineStats.ts
|
|
735
|
-
function engineStats(engine, data
|
|
736
|
-
return { engine, data, fallbackUsed };
|
|
1361
|
+
function engineStats(engine, data) {
|
|
1362
|
+
return { engine, data, fallbackUsed: false };
|
|
737
1363
|
}
|
|
738
1364
|
function selectedEngineStats(requested, engine, data) {
|
|
739
|
-
|
|
1365
|
+
if (requested !== engine) {
|
|
1366
|
+
throw new Error(`brass-runtime strict engine mismatch: requested '${requested}', got '${engine}'`);
|
|
1367
|
+
}
|
|
1368
|
+
return { requested, engine, data, fallbackUsed: false };
|
|
740
1369
|
}
|
|
741
1370
|
export {
|
|
1371
|
+
ABI_VERSION,
|
|
742
1372
|
Async,
|
|
743
1373
|
Cause,
|
|
744
1374
|
DefaultHostExecutor,
|
|
1375
|
+
EVENT_WORDS,
|
|
745
1376
|
EngineFiberHandle,
|
|
1377
|
+
EventKindCode,
|
|
746
1378
|
Exit,
|
|
747
1379
|
HostRegistry,
|
|
748
1380
|
JsFiberEngine,
|
|
1381
|
+
NONE_U32,
|
|
749
1382
|
NoopHooks,
|
|
1383
|
+
OpcodeTagCode,
|
|
1384
|
+
PURE_PIPELINE_TAG,
|
|
750
1385
|
ProgramBuilder,
|
|
751
1386
|
PushStatus,
|
|
752
|
-
ReferenceWasmBridge,
|
|
753
1387
|
RingBuffer,
|
|
754
1388
|
Runtime,
|
|
755
1389
|
RuntimeFiber,
|
|
@@ -758,10 +1392,17 @@ export {
|
|
|
758
1392
|
WasmFiberEngine,
|
|
759
1393
|
WasmFiberRegistryBridge,
|
|
760
1394
|
WasmPackFiberBridge,
|
|
1395
|
+
abortablePromiseStats,
|
|
761
1396
|
acquireRelease,
|
|
762
|
-
andThen,
|
|
1397
|
+
andThen2 as andThen,
|
|
1398
|
+
andThen as andThenSchedule,
|
|
1399
|
+
applyFused,
|
|
1400
|
+
assertCompletesWithin,
|
|
1401
|
+
assertFails,
|
|
1402
|
+
assertFailsWith,
|
|
763
1403
|
assertNever,
|
|
764
|
-
|
|
1404
|
+
assertSucceeds,
|
|
1405
|
+
asyncEffect as async,
|
|
765
1406
|
asyncCatchAll,
|
|
766
1407
|
asyncFail,
|
|
767
1408
|
asyncFlatMap,
|
|
@@ -773,25 +1414,43 @@ export {
|
|
|
773
1414
|
asyncSync,
|
|
774
1415
|
asyncTotal,
|
|
775
1416
|
bounded,
|
|
1417
|
+
bracket,
|
|
776
1418
|
broadcast,
|
|
777
1419
|
broadcastToHub,
|
|
778
1420
|
buffer,
|
|
779
1421
|
bufferP,
|
|
780
1422
|
catchAll,
|
|
1423
|
+
catchTag,
|
|
1424
|
+
catchTags,
|
|
781
1425
|
chunks,
|
|
782
1426
|
chunksP,
|
|
783
1427
|
collectAllPar,
|
|
784
1428
|
collectStream,
|
|
785
|
-
compose,
|
|
1429
|
+
compose2 as compose,
|
|
1430
|
+
compose as composeLayer,
|
|
786
1431
|
concatStream,
|
|
1432
|
+
debounce,
|
|
1433
|
+
decodeEvent,
|
|
1434
|
+
decodeEventBatch,
|
|
1435
|
+
delayedEffect,
|
|
1436
|
+
derivedRef,
|
|
1437
|
+
deserializeFusedPipeline,
|
|
787
1438
|
dropP,
|
|
1439
|
+
drop as dropStream,
|
|
1440
|
+
elapsed,
|
|
788
1441
|
emitStream,
|
|
789
1442
|
emptyStream,
|
|
1443
|
+
encodeOpcodeNodes,
|
|
1444
|
+
encodeOpcodeProgram,
|
|
790
1445
|
end,
|
|
791
1446
|
engineStats,
|
|
1447
|
+
ensuring,
|
|
1448
|
+
exponential,
|
|
792
1449
|
fail,
|
|
793
1450
|
filterMapP,
|
|
794
1451
|
filterP,
|
|
1452
|
+
fixed,
|
|
1453
|
+
flakyEffect,
|
|
795
1454
|
flatMap,
|
|
796
1455
|
flattenStream,
|
|
797
1456
|
foreachStream,
|
|
@@ -800,16 +1459,41 @@ export {
|
|
|
800
1459
|
fromHub,
|
|
801
1460
|
fromPromiseAbortable,
|
|
802
1461
|
fromPull,
|
|
1462
|
+
fuse,
|
|
803
1463
|
getBenchmarkBudget,
|
|
804
1464
|
getCurrentFiber,
|
|
1465
|
+
getStats,
|
|
805
1466
|
globalScheduler,
|
|
1467
|
+
gracefulShutdown,
|
|
806
1468
|
groupedP,
|
|
807
1469
|
identity,
|
|
1470
|
+
inferCallerLaneFromStack,
|
|
1471
|
+
initState,
|
|
1472
|
+
interleave,
|
|
1473
|
+
intersect,
|
|
1474
|
+
isFusionEnabled,
|
|
1475
|
+
isFusionVerbose,
|
|
1476
|
+
jittered,
|
|
1477
|
+
laneTag,
|
|
1478
|
+
layer,
|
|
1479
|
+
layerFail,
|
|
1480
|
+
layerFrom,
|
|
1481
|
+
layerSucceed,
|
|
808
1482
|
linkAbortController,
|
|
809
1483
|
makeBoundedRingBuffer,
|
|
810
1484
|
makeCancelToken,
|
|
1485
|
+
makeCircuitBreaker,
|
|
1486
|
+
makeFiberReadyQueue,
|
|
811
1487
|
makeHub,
|
|
1488
|
+
makeMetrics,
|
|
1489
|
+
makeRef,
|
|
1490
|
+
makeSemaphore,
|
|
812
1491
|
makeStreamChunker,
|
|
1492
|
+
makeTestRuntime,
|
|
1493
|
+
makeTracer,
|
|
1494
|
+
makeWorkerPool,
|
|
1495
|
+
managed,
|
|
1496
|
+
managedAll,
|
|
813
1497
|
managedStream,
|
|
814
1498
|
map,
|
|
815
1499
|
mapAsync,
|
|
@@ -818,38 +1502,71 @@ export {
|
|
|
818
1502
|
mapChunksEffectP,
|
|
819
1503
|
mapEffectP,
|
|
820
1504
|
mapError,
|
|
1505
|
+
mapError2 as mapErrorTyped,
|
|
1506
|
+
mapLayer,
|
|
821
1507
|
mapP,
|
|
822
1508
|
mapStream,
|
|
823
1509
|
mapTryAsync,
|
|
824
|
-
merge,
|
|
1510
|
+
merge2 as merge,
|
|
1511
|
+
merge as mergeLayer,
|
|
825
1512
|
mergeStream,
|
|
1513
|
+
neverEffect,
|
|
826
1514
|
none,
|
|
1515
|
+
orElse,
|
|
827
1516
|
orElseOptional,
|
|
1517
|
+
provideLayer,
|
|
828
1518
|
race,
|
|
829
1519
|
raceWith,
|
|
830
1520
|
rangeStream,
|
|
1521
|
+
recurs,
|
|
1522
|
+
registerShutdownHooks,
|
|
1523
|
+
repeatWithSchedule,
|
|
1524
|
+
resetAbortablePromiseStats,
|
|
1525
|
+
retry,
|
|
1526
|
+
retryN,
|
|
1527
|
+
retryWithBackoff,
|
|
1528
|
+
retryWithSchedule,
|
|
1529
|
+
runFusedArray,
|
|
831
1530
|
runtimeCapabilities,
|
|
1531
|
+
runtimeForCaller,
|
|
1532
|
+
sanitizeLaneKey,
|
|
1533
|
+
scan,
|
|
832
1534
|
selectedEngineStats,
|
|
1535
|
+
serializeFusedPipeline,
|
|
833
1536
|
setBenchmarkBudget,
|
|
1537
|
+
setFusionEnabled,
|
|
1538
|
+
setFusionVerbose,
|
|
1539
|
+
sleep,
|
|
834
1540
|
some,
|
|
835
1541
|
streamFromReadableStream,
|
|
836
1542
|
succeed,
|
|
837
1543
|
sync,
|
|
1544
|
+
tagError,
|
|
838
1545
|
takeP,
|
|
1546
|
+
take as takeSchedule,
|
|
1547
|
+
take2 as takeStream,
|
|
839
1548
|
tapEffectP,
|
|
1549
|
+
throttle,
|
|
1550
|
+
timeout,
|
|
840
1551
|
toPromise,
|
|
1552
|
+
toPromiseByCaller,
|
|
841
1553
|
uncons,
|
|
1554
|
+
union,
|
|
842
1555
|
unit,
|
|
843
1556
|
unsafeGetCurrentRuntime,
|
|
844
1557
|
unsafeRunAsync,
|
|
845
1558
|
unsafeRunFoldWithEnv,
|
|
846
1559
|
unwrapScoped,
|
|
1560
|
+
useManaged,
|
|
847
1561
|
via,
|
|
1562
|
+
whileInput,
|
|
848
1563
|
widenOpt,
|
|
849
1564
|
withAsyncPromise,
|
|
850
1565
|
withCurrentFiber,
|
|
851
1566
|
withScope,
|
|
852
1567
|
withScopeAsync,
|
|
853
1568
|
zip,
|
|
854
|
-
zipPar
|
|
1569
|
+
zipPar,
|
|
1570
|
+
zip2 as zipStream,
|
|
1571
|
+
zipWith
|
|
855
1572
|
};
|