brass-runtime 1.13.7 → 1.14.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.
Files changed (37) hide show
  1. package/README.md +231 -55
  2. package/dist/agent/cli/main.cjs +43 -43
  3. package/dist/agent/cli/main.js +2 -2
  4. package/dist/agent/cli/main.mjs +2 -2
  5. package/dist/agent/index.cjs +3 -3
  6. package/dist/agent/index.d.ts +1 -1
  7. package/dist/agent/index.js +2 -2
  8. package/dist/agent/index.mjs +2 -2
  9. package/dist/chunk-4N2JEK4H.mjs +3897 -0
  10. package/dist/chunk-BKBFSOGT.cjs +3897 -0
  11. package/dist/{chunk-XNOTJSMZ.mjs → chunk-BMRF4FN6.js} +268 -8
  12. package/dist/chunk-JT7D6M5H.js +3897 -0
  13. package/dist/{chunk-3R7ZYRK2.mjs → chunk-MQF7HZ7Y.mjs} +1 -1
  14. package/dist/chunk-SKVY72E5.cjs +667 -0
  15. package/dist/{chunk-ATHSSDUF.js → chunk-UWMMYKVK.mjs} +268 -8
  16. package/dist/{chunk-INZBKOHY.js → chunk-WJESVBWN.js} +1 -1
  17. package/dist/{chunk-XDINDYNA.cjs → chunk-XTMZTVIT.cjs} +134 -134
  18. package/dist/{effect-ISvXPLgc.d.ts → effect-DM56H743.d.ts} +191 -21
  19. package/dist/http/index.cjs +808 -140
  20. package/dist/http/index.d.ts +181 -8
  21. package/dist/http/index.js +793 -125
  22. package/dist/http/index.mjs +793 -125
  23. package/dist/index.cjs +1785 -137
  24. package/dist/index.d.ts +979 -36
  25. package/dist/index.js +1675 -27
  26. package/dist/index.mjs +1675 -27
  27. package/dist/stream-Oqe6WeLE.d.ts +173 -0
  28. package/package.json +1 -1
  29. package/wasm/pkg/brass_runtime_wasm_engine.d.ts +95 -16
  30. package/wasm/pkg/brass_runtime_wasm_engine.js +715 -15
  31. package/wasm/pkg/brass_runtime_wasm_engine_bg.wasm +0 -0
  32. package/wasm/pkg/brass_runtime_wasm_engine_bg.wasm.d.ts +78 -7
  33. package/dist/chunk-2P4PD6D7.cjs +0 -2557
  34. package/dist/chunk-7F2R7A2V.mjs +0 -2557
  35. package/dist/chunk-L6KKKM66.js +0 -2557
  36. package/dist/chunk-ZTDK2DLG.cjs +0 -407
  37. package/dist/stream-BvukHxCv.d.ts +0 -66
@@ -1,2557 +0,0 @@
1
- // src/core/types/asyncEffect.ts
2
- var Async = {
3
- succeed: (value) => ({ _tag: "Succeed", value }),
4
- fail: (error) => ({ _tag: "Fail", error }),
5
- sync: (thunk) => ({ _tag: "Sync", thunk }),
6
- async: (register) => ({ _tag: "Async", register })
7
- };
8
- function asyncFold(fa, onFailure, onSuccess) {
9
- return { _tag: "Fold", first: fa, onFailure, onSuccess };
10
- }
11
- function asyncCatchAll(fa, handler) {
12
- return asyncFold(
13
- fa,
14
- (e) => handler(e),
15
- (a) => asyncSucceed(a)
16
- );
17
- }
18
- function asyncMapError(fa, f) {
19
- return asyncFold(
20
- fa,
21
- (e) => asyncFail(f(e)),
22
- (a) => asyncSucceed(a)
23
- );
24
- }
25
- var SUCCEED_UNDEFINED = { _tag: "Succeed", value: void 0 };
26
- var SUCCEED_TRUE = { _tag: "Succeed", value: true };
27
- var SUCCEED_FALSE = { _tag: "Succeed", value: false };
28
- var SUCCEED_NULL = { _tag: "Succeed", value: null };
29
- var unit = () => SUCCEED_UNDEFINED;
30
- var asyncSucceed = (value) => {
31
- if (value === void 0) return SUCCEED_UNDEFINED;
32
- if (value === true) return SUCCEED_TRUE;
33
- if (value === false) return SUCCEED_FALSE;
34
- if (value === null) return SUCCEED_NULL;
35
- return { _tag: "Succeed", value };
36
- };
37
- var asyncFail = (error) => ({
38
- _tag: "Fail",
39
- error
40
- });
41
- var asyncSync = (thunk) => ({
42
- _tag: "Sync",
43
- thunk
44
- });
45
- var asyncTotal = (thunk) => asyncSync(() => thunk());
46
- var async = (register) => ({
47
- _tag: "Async",
48
- register
49
- });
50
- function asyncMap(fa, f) {
51
- return asyncFlatMap(fa, (a) => asyncSucceed(f(a)));
52
- }
53
- function asyncFlatMap(fa, f) {
54
- return {
55
- _tag: "FlatMap",
56
- first: fa,
57
- andThen: f
58
- };
59
- }
60
- function acquireRelease(acquire, release, scope) {
61
- return asyncFlatMap(acquire, (resource) => {
62
- scope.addFinalizer((exit) => release(resource, exit));
63
- return asyncSucceed(resource);
64
- });
65
- }
66
- function asyncInterruptible(register) {
67
- return async(register);
68
- }
69
- var withAsyncPromise = (run) => (eff) => {
70
- const anyEff = eff;
71
- if (!anyEff.toPromise) {
72
- anyEff.toPromise = (env) => run(eff, env);
73
- anyEff.unsafeRunPromise = () => run(eff, {});
74
- }
75
- return anyEff;
76
- };
77
- var mapAsync = (fa, f) => asyncFlatMap(fa, (a) => asyncSucceed(f(a)));
78
- var mapTryAsync = (fa, f) => asyncFlatMap(fa, (a) => asyncSync(() => f(a)));
79
-
80
- // src/core/types/option.ts
81
- var none = { _tag: "None" };
82
- var some = (value) => ({ _tag: "Some", value });
83
-
84
- // src/core/types/effect.ts
85
- var Cause = {
86
- fail: (error) => ({ _tag: "Fail", error }),
87
- interrupt: () => ({ _tag: "Interrupt" }),
88
- die: (defect) => ({ _tag: "Die", defect })
89
- };
90
- var Exit = {
91
- succeed: (value) => ({
92
- _tag: "Success",
93
- value
94
- }),
95
- failCause: (cause) => ({
96
- _tag: "Failure",
97
- cause
98
- })
99
- };
100
- var succeed = (value) => asyncSucceed(value);
101
- var fail = (error) => asyncFail(error);
102
- var sync = (thunk) => asyncSync((env) => thunk(env));
103
- var map = (fa, f) => asyncMap(fa, f);
104
- var flatMap = (fa, f) => asyncFlatMap(fa, (a) => f(a));
105
- var mapError = (fa, f) => asyncMapError(fa, f);
106
- var catchAll = (fa, handler) => asyncFold(
107
- fa,
108
- (e) => handler(e),
109
- (a) => asyncSucceed(a)
110
- );
111
- function orElseOptional(fa, that) {
112
- return asyncFold(
113
- fa,
114
- (opt) => opt._tag === "Some" ? asyncFail(opt) : that(),
115
- (a) => asyncSucceed(a)
116
- );
117
- }
118
- var end = () => fail(none);
119
-
120
- // src/core/runtime/ringBuffer.ts
121
- var PushStatus = /* @__PURE__ */ ((PushStatus3) => {
122
- PushStatus3[PushStatus3["Ok"] = 0] = "Ok";
123
- PushStatus3[PushStatus3["Grew"] = 1] = "Grew";
124
- PushStatus3[PushStatus3["Dropped"] = 2] = "Dropped";
125
- return PushStatus3;
126
- })(PushStatus || {});
127
- var RingBuffer = class {
128
- buf;
129
- head = 0;
130
- tail = 0;
131
- size_ = 0;
132
- // nuevo
133
- maxCap;
134
- constructor(initialCapacity = 1024, maxCapacity = initialCapacity) {
135
- let initPow = Math.max(2, initialCapacity);
136
- initPow--;
137
- initPow |= initPow >>> 1;
138
- initPow |= initPow >>> 2;
139
- initPow |= initPow >>> 4;
140
- initPow |= initPow >>> 8;
141
- initPow |= initPow >>> 16;
142
- initPow++;
143
- let maxPow = Math.max(initPow, maxCapacity);
144
- maxPow--;
145
- maxPow |= maxPow >>> 1;
146
- maxPow |= maxPow >>> 2;
147
- maxPow |= maxPow >>> 4;
148
- maxPow |= maxPow >>> 8;
149
- maxPow |= maxPow >>> 16;
150
- maxPow++;
151
- this.buf = new Array(initPow);
152
- this.maxCap = maxPow;
153
- }
154
- get length() {
155
- return this.size_;
156
- }
157
- get capacity() {
158
- return this.buf.length;
159
- }
160
- isEmpty() {
161
- return this.size_ === 0;
162
- }
163
- push(value) {
164
- if (this.size_ === this.buf.length) {
165
- if (this.buf.length >= this.maxCap) {
166
- return 2 /* Dropped */;
167
- }
168
- this.grow();
169
- this.buf[this.tail] = value;
170
- this.tail = this.tail + 1 & this.buf.length - 1;
171
- this.size_++;
172
- return 0 /* Ok */ | 1 /* Grew */;
173
- }
174
- this.buf[this.tail] = value;
175
- this.tail = this.tail + 1 & this.buf.length - 1;
176
- this.size_++;
177
- return 0 /* Ok */;
178
- }
179
- shift() {
180
- if (this.size_ === 0) return void 0;
181
- const value = this.buf[this.head];
182
- this.buf[this.head] = void 0;
183
- this.head = this.head + 1 & this.buf.length - 1;
184
- this.size_--;
185
- return value;
186
- }
187
- clear() {
188
- this.head = 0;
189
- this.tail = 0;
190
- this.size_ = 0;
191
- }
192
- grow() {
193
- const old = this.buf;
194
- const nextLen = Math.min(old.length * 2, this.maxCap);
195
- const newBuf = new Array(nextLen);
196
- for (let i = 0; i < this.size_; i++) {
197
- newBuf[i] = old[this.head + i & old.length - 1];
198
- }
199
- this.buf = newBuf;
200
- this.head = 0;
201
- this.tail = this.size_;
202
- }
203
- };
204
-
205
- // src/core/runtime/wasmModule.ts
206
- import { createRequire } from "module";
207
- var cachedWasmModule;
208
- var cachedWasmModuleErrors = [];
209
- function resolveWasmModule(options = {}) {
210
- if (!options.fresh && options.modulePath == null && cachedWasmModule !== void 0) {
211
- return cachedWasmModule;
212
- }
213
- const req = getBestRequire();
214
- const candidates = wasmModuleCandidates(options.modulePath);
215
- const errors = [];
216
- if (!req) {
217
- errors.push("no CommonJS-compatible require/createRequire was available");
218
- return remember(options, null, errors);
219
- }
220
- for (const candidate of candidates) {
221
- try {
222
- return remember(options, req(candidate), errors);
223
- } catch (error) {
224
- errors.push(`${candidate}: ${formatError(error)}`);
225
- }
226
- }
227
- return remember(options, null, errors);
228
- }
229
- function wasmModuleResolutionErrors() {
230
- return cachedWasmModuleErrors.slice();
231
- }
232
- function wasmModuleCandidates(modulePath) {
233
- if (modulePath) return [modulePath];
234
- return [
235
- "brass-runtime/wasm/pkg/brass_runtime_wasm_engine.js",
236
- "../wasm/pkg/brass_runtime_wasm_engine.js",
237
- "../../../wasm/pkg/brass_runtime_wasm_engine.js",
238
- "../../../../../wasm/pkg/brass_runtime_wasm_engine.js",
239
- `${getCwd()}/wasm/pkg/brass_runtime_wasm_engine.js`
240
- ];
241
- }
242
- function remember(options, value, errors) {
243
- if (!options.fresh && options.modulePath == null) {
244
- cachedWasmModule = value;
245
- cachedWasmModuleErrors = errors;
246
- }
247
- return value;
248
- }
249
- function getBestRequire() {
250
- return getNonWebpackRequire() ?? getRuntimeRequire() ?? getCreateRequire();
251
- }
252
- function getNonWebpackRequire() {
253
- try {
254
- return (0, eval)(
255
- "typeof __non_webpack_require__ === 'function' ? __non_webpack_require__ : undefined"
256
- );
257
- } catch {
258
- return void 0;
259
- }
260
- }
261
- function getRuntimeRequire() {
262
- try {
263
- return (0, eval)(
264
- "typeof require === 'function' ? require : undefined"
265
- );
266
- } catch {
267
- return void 0;
268
- }
269
- }
270
- function getCreateRequire() {
271
- try {
272
- return createRequire(`${getCwd()}/package.json`);
273
- } catch {
274
- return void 0;
275
- }
276
- }
277
- function getCwd() {
278
- try {
279
- return (0, eval)(
280
- "typeof process !== 'undefined' ? process.cwd() : ''"
281
- );
282
- } catch {
283
- return "";
284
- }
285
- }
286
- function formatError(error) {
287
- return error instanceof Error ? error.message : String(error);
288
- }
289
-
290
- // src/core/runtime/boundedRingBuffer.ts
291
- var cachedWasmCtor;
292
- function resolveWasmRingBuffer() {
293
- if (cachedWasmCtor !== void 0) return cachedWasmCtor;
294
- const mod = resolveWasmModule();
295
- cachedWasmCtor = mod?.BrassWasmRingBuffer ?? null;
296
- return cachedWasmCtor;
297
- }
298
- var WasmRingBuffer = class {
299
- engine = "wasm";
300
- fallbackUsed = false;
301
- inner;
302
- pushes = 0;
303
- shifts = 0;
304
- clears = 0;
305
- dropped = 0;
306
- constructor(initialCapacity, maxCapacity) {
307
- const Ctor = resolveWasmRingBuffer();
308
- if (!Ctor) {
309
- throw new Error("brass-runtime wasm ring buffer is not available. Run npm run build:wasm first.");
310
- }
311
- this.inner = new Ctor(initialCapacity, maxCapacity);
312
- }
313
- get length() {
314
- return this.inner.len();
315
- }
316
- get capacity() {
317
- return this.inner.capacity();
318
- }
319
- isEmpty() {
320
- return this.inner.is_empty();
321
- }
322
- push(value) {
323
- this.pushes++;
324
- const status = this.inner.push(value);
325
- if ((status & 2) !== 0) this.dropped++;
326
- return status;
327
- }
328
- shift() {
329
- const value = this.inner.shift();
330
- if (value !== void 0) this.shifts++;
331
- return value === void 0 ? void 0 : value;
332
- }
333
- clear() {
334
- this.clears++;
335
- this.inner.clear();
336
- }
337
- stats() {
338
- return {
339
- engine: "wasm",
340
- fallbackUsed: false,
341
- data: {
342
- len: this.length,
343
- capacity: this.capacity,
344
- pushes: this.pushes,
345
- shifts: this.shifts,
346
- clears: this.clears,
347
- dropped: this.dropped
348
- }
349
- };
350
- }
351
- };
352
- var JsBoundedRingBuffer = class {
353
- constructor(inner, fallbackUsed) {
354
- this.inner = inner;
355
- this.fallbackUsed = fallbackUsed;
356
- }
357
- inner;
358
- fallbackUsed;
359
- engine = "js";
360
- pushes = 0;
361
- shifts = 0;
362
- clears = 0;
363
- dropped = 0;
364
- get length() {
365
- return this.inner.length;
366
- }
367
- get capacity() {
368
- return this.inner.capacity;
369
- }
370
- isEmpty() {
371
- return this.inner.isEmpty();
372
- }
373
- push(value) {
374
- this.pushes++;
375
- const status = this.inner.push(value);
376
- if ((status & 2) !== 0) this.dropped++;
377
- return status;
378
- }
379
- shift() {
380
- const value = this.inner.shift();
381
- if (value !== void 0) this.shifts++;
382
- return value;
383
- }
384
- clear() {
385
- this.clears++;
386
- this.inner.clear();
387
- }
388
- stats() {
389
- return {
390
- engine: "js",
391
- fallbackUsed: this.fallbackUsed,
392
- data: {
393
- len: this.length,
394
- capacity: this.capacity,
395
- pushes: this.pushes,
396
- shifts: this.shifts,
397
- clears: this.clears,
398
- dropped: this.dropped
399
- }
400
- };
401
- }
402
- };
403
- function makeBoundedRingBuffer(initialCapacity, maxCapacity = initialCapacity, options = {}) {
404
- const engine = options.engine ?? "auto";
405
- if (engine === "js") {
406
- return new JsBoundedRingBuffer(new RingBuffer(initialCapacity, maxCapacity), false);
407
- }
408
- if (engine === "wasm") {
409
- return new WasmRingBuffer(initialCapacity, maxCapacity);
410
- }
411
- const Ctor = resolveWasmRingBuffer();
412
- if (Ctor) {
413
- return new WasmRingBuffer(initialCapacity, maxCapacity);
414
- }
415
- return new JsBoundedRingBuffer(new RingBuffer(initialCapacity, maxCapacity), true);
416
- }
417
-
418
- // src/core/runtime/scheduler.ts
419
- var FLUSH_BUDGET = 2048;
420
- var MICRO_THRESHOLD = 4096;
421
- var SCHEDULER_QUEUE_CAPACITY = 8192;
422
- var scheduleMacro = (() => {
423
- if (typeof globalThis.setImmediate === "function") {
424
- return (f) => globalThis.setImmediate(f);
425
- }
426
- if (typeof globalThis.MessageChannel === "function") {
427
- const ch = new globalThis.MessageChannel();
428
- let cb = null;
429
- ch.port1.onmessage = () => {
430
- const f = cb;
431
- cb = null;
432
- f?.();
433
- };
434
- return (f) => {
435
- cb = f;
436
- ch.port2.postMessage(0);
437
- };
438
- }
439
- return (f) => setTimeout(f, 0);
440
- })();
441
- function resolveWasmScheduler() {
442
- const mod = resolveWasmModule();
443
- return mod?.BrassWasmSchedulerStateMachine ?? null;
444
- }
445
- var JsSchedulerState = class {
446
- tasks;
447
- tags;
448
- flushing = false;
449
- scheduled = false;
450
- scheduledFlushes = 0;
451
- completedFlushes = 0;
452
- enqueuedTasks = 0;
453
- executedTasks = 0;
454
- droppedTasks = 0;
455
- yieldedByBudget = 0;
456
- constructor(options) {
457
- const initial = options.initialCapacity ?? 1024;
458
- const max = options.maxCapacity ?? initial;
459
- this.tasks = makeBoundedRingBuffer(initial, max, { engine: options.engine });
460
- this.tags = makeBoundedRingBuffer(initial, max, { engine: options.engine });
461
- }
462
- };
463
- var WasmSchedulerState = class {
464
- machine;
465
- nextRef = 1;
466
- tasks = /* @__PURE__ */ new Map();
467
- tags = /* @__PURE__ */ new Map();
468
- constructor(options) {
469
- const Ctor = resolveWasmScheduler();
470
- if (!Ctor) throw new Error("brass-runtime wasm scheduler is not available. Run npm run build:wasm first.");
471
- this.machine = new Ctor(
472
- options.initialCapacity ?? 1024,
473
- options.maxCapacity ?? SCHEDULER_QUEUE_CAPACITY,
474
- options.flushBudget ?? FLUSH_BUDGET,
475
- options.microThreshold ?? MICRO_THRESHOLD
476
- );
477
- }
478
- enqueue(task, tag) {
479
- const ref = this.nextRef++;
480
- this.tasks.set(ref, task);
481
- this.tags.set(ref, tag);
482
- const policy = this.machine.enqueue(ref);
483
- if (policy === 3) {
484
- this.tasks.delete(ref);
485
- this.tags.delete(ref);
486
- }
487
- return policy;
488
- }
489
- beginFlush() {
490
- return this.machine.begin_flush();
491
- }
492
- shift() {
493
- const ref = this.machine.shift();
494
- if (ref === 0) return void 0;
495
- const task = this.tasks.get(ref);
496
- const tag = this.tags.get(ref) ?? "anonymous";
497
- this.tasks.delete(ref);
498
- this.tags.delete(ref);
499
- return task ? { task, tag } : void 0;
500
- }
501
- endFlush(ran) {
502
- return this.machine.end_flush(ran);
503
- }
504
- get length() {
505
- return this.machine.len();
506
- }
507
- stats() {
508
- return { engine: "wasm", fallbackUsed: false, data: JSON.parse(this.machine.stats_json()) };
509
- }
510
- };
511
- var Scheduler = class {
512
- engine;
513
- js;
514
- wasm;
515
- flushBudget;
516
- microThreshold;
517
- fallbackUsed;
518
- // Cached flush closure — avoids creating a new closure on every requestFlush
519
- boundFlush = () => this.flush();
520
- constructor(options = {}) {
521
- this.flushBudget = options.flushBudget ?? FLUSH_BUDGET;
522
- this.microThreshold = options.microThreshold ?? MICRO_THRESHOLD;
523
- const requested = options.engine ?? "js";
524
- if (requested === "wasm") {
525
- this.wasm = new WasmSchedulerState(options);
526
- this.engine = "wasm";
527
- this.fallbackUsed = false;
528
- return;
529
- }
530
- if (requested === "auto" && resolveWasmScheduler()) {
531
- this.wasm = new WasmSchedulerState(options);
532
- this.engine = "wasm";
533
- this.fallbackUsed = false;
534
- return;
535
- }
536
- this.js = new JsSchedulerState({ ...options, engine: "js" });
537
- this.engine = "js";
538
- this.fallbackUsed = requested === "auto";
539
- }
540
- schedule(task, tag = "anonymous") {
541
- if (typeof task !== "function") return;
542
- if (this.wasm) return this.scheduleWasm(task, tag);
543
- this.scheduleJs(task, tag);
544
- }
545
- stats() {
546
- if (this.wasm) return this.wasm.stats();
547
- const js = this.js;
548
- return {
549
- engine: "js",
550
- fallbackUsed: this.fallbackUsed,
551
- data: {
552
- len: js.tasks.length,
553
- capacity: js.tasks.capacity,
554
- phase: js.flushing ? "flushing" : js.scheduled ? "scheduled" : "idle",
555
- scheduledFlushes: js.scheduledFlushes,
556
- completedFlushes: js.completedFlushes,
557
- enqueuedTasks: js.enqueuedTasks,
558
- executedTasks: js.executedTasks,
559
- droppedTasks: js.droppedTasks,
560
- yieldedByBudget: js.yieldedByBudget
561
- }
562
- };
563
- }
564
- scheduleWasm(task, tag) {
565
- const policy = this.wasm.enqueue(task, tag);
566
- if (policy === 0) this.requestFlush("micro");
567
- else if (policy === 1) this.requestFlush("macro");
568
- }
569
- scheduleJs(task, tag) {
570
- const js = this.js;
571
- const taskStatus = js.tasks.push(task);
572
- const tagStatus = js.tags.push(tag);
573
- js.enqueuedTasks++;
574
- if ((taskStatus & 2) !== 0 || (tagStatus & 2) !== 0) js.droppedTasks++;
575
- if (js.flushing) return;
576
- if (!js.scheduled) {
577
- js.scheduled = true;
578
- js.scheduledFlushes++;
579
- const kind = js.tasks.length > this.microThreshold ? "macro" : "micro";
580
- this.requestFlush(kind);
581
- }
582
- }
583
- requestFlush(kind) {
584
- if (kind === "micro") queueMicrotask(this.boundFlush);
585
- else scheduleMacro(this.boundFlush);
586
- }
587
- flush() {
588
- if (this.wasm) return this.flushWasm();
589
- this.flushJs();
590
- }
591
- flushWasm() {
592
- const wasm = this.wasm;
593
- const budget = wasm.beginFlush();
594
- if (budget <= 0) return;
595
- let ran = 0;
596
- try {
597
- while (ran < budget) {
598
- const next = wasm.shift();
599
- if (!next) break;
600
- ran++;
601
- try {
602
- next.task();
603
- } catch (e) {
604
- console.error(`[Scheduler] task threw (tag=${next.tag})`, e);
605
- }
606
- }
607
- } finally {
608
- const policy = wasm.endFlush(ran);
609
- if (policy === 0) this.requestFlush("micro");
610
- else if (policy === 1) this.requestFlush("macro");
611
- }
612
- }
613
- flushJs() {
614
- const js = this.js;
615
- if (js.flushing) return;
616
- js.flushing = true;
617
- js.scheduled = false;
618
- let ran = 0;
619
- try {
620
- while (ran < this.flushBudget) {
621
- const task = js.tasks.shift();
622
- if (!task) break;
623
- const tag = js.tags.shift();
624
- ran++;
625
- js.executedTasks++;
626
- try {
627
- task();
628
- } catch (e) {
629
- console.error(`[Scheduler] task threw (tag=${tag})`, e);
630
- }
631
- }
632
- } finally {
633
- js.flushing = false;
634
- js.completedFlushes++;
635
- if (js.tasks.length > 0 && !js.scheduled) {
636
- js.scheduled = true;
637
- js.scheduledFlushes++;
638
- const kind = ran >= this.flushBudget || js.tasks.length > this.microThreshold ? "macro" : "micro";
639
- if (ran >= this.flushBudget) js.yieldedByBudget++;
640
- this.requestFlush(kind);
641
- }
642
- }
643
- }
644
- };
645
- var globalScheduler = new Scheduler();
646
-
647
- // src/core/runtime/contex.ts
648
- var emptyContext = { parent: null, patch: /* @__PURE__ */ Object.create(null) };
649
-
650
- // src/core/runtime/forkPolicy.ts
651
- function makeForkPolicy(env, hooks) {
652
- const svc = resolveForkServices(env);
653
- return {
654
- initChild(fiber, parent, scopeId) {
655
- const parentCtx = parent?.fiberContext;
656
- const trace = forkTrace(svc, parentCtx?.trace ?? null);
657
- fiber.fiberContext = {
658
- log: parentCtx?.log ?? emptyContext,
659
- trace
660
- };
661
- fiber.parentFiberId = parent?.id;
662
- fiber.name = svc.childName(parent?.name);
663
- if (scopeId !== void 0) fiber.scopeId = scopeId;
664
- hooks.emit(
665
- {
666
- type: "fiber.start",
667
- fiberId: fiber.id,
668
- parentFiberId: parent?.id,
669
- scopeId: fiber.scopeId,
670
- // ✅ ahora viaja
671
- name: fiber.name
672
- },
673
- { fiberId: parent?.id, traceId: parentCtx?.trace?.traceId, spanId: parentCtx?.trace?.spanId }
674
- );
675
- }
676
- };
677
- }
678
- function resolveForkServices(env) {
679
- const defaultTracer = {
680
- newTraceId: () => randomRuntimeId("trace"),
681
- newSpanId: () => randomRuntimeId("span")
682
- };
683
- const brass = env?.brass;
684
- const tracer = brass?.tracer ?? defaultTracer;
685
- const seed = brass?.traceSeed;
686
- const childName = brass?.childName ?? ((p) => p ? `${p}/child` : void 0);
687
- return { tracer, seed, childName };
688
- }
689
- function randomRuntimeId(prefix) {
690
- const cryptoLike = globalThis.crypto;
691
- if (typeof cryptoLike?.randomUUID === "function") {
692
- return cryptoLike.randomUUID();
693
- }
694
- return `${prefix}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
695
- }
696
- function forkTrace(svc, parentTrace) {
697
- if (parentTrace) {
698
- return {
699
- traceId: parentTrace.traceId,
700
- spanId: svc.tracer.newSpanId(),
701
- parentSpanId: parentTrace.spanId,
702
- sampled: parentTrace.sampled
703
- };
704
- }
705
- if (svc.seed) return { ...svc.seed };
706
- return { traceId: svc.tracer.newTraceId(), spanId: svc.tracer.newSpanId(), sampled: true };
707
- }
708
-
709
- // src/core/runtime/hostAction.ts
710
- var DefaultHostExecutor = {
711
- async execute(action) {
712
- return {
713
- kind: "error",
714
- actionId: action.actionId,
715
- error: new Error(`No HostExecutor configured for HostAction kind=${action.kind} target=${action.target}`)
716
- };
717
- }
718
- };
719
-
720
- // src/core/runtime/engine/JsFiberEngine.ts
721
- var JsFiberEngine = class {
722
- constructor(runtime) {
723
- this.runtime = runtime;
724
- }
725
- runtime;
726
- kind = "js";
727
- startedFibers = 0;
728
- fork(effect, scopeId) {
729
- this.startedFibers += 1;
730
- const fiber = new RuntimeFiber(this.runtime, effect);
731
- if (scopeId !== void 0) fiber.scopeId = scopeId;
732
- return fiber;
733
- }
734
- stats() {
735
- return {
736
- engine: this.kind,
737
- startedFibers: this.startedFibers,
738
- runningFibers: 0,
739
- suspendedFibers: 0,
740
- queuedFibers: 0,
741
- completedFibers: 0,
742
- failedFibers: 0,
743
- interruptedFibers: 0,
744
- pendingHostEffects: 0
745
- };
746
- }
747
- };
748
-
749
- // src/core/runtime/engine/opcodes.ts
750
- var HostRegistry = class {
751
- nextRef = 1;
752
- refs = /* @__PURE__ */ new Map();
753
- register(value) {
754
- const ref = this.nextRef++;
755
- this.refs.set(ref, value);
756
- return ref;
757
- }
758
- get(ref) {
759
- if (!this.refs.has(ref)) {
760
- throw new Error(`Missing host registry ref ${ref}`);
761
- }
762
- return this.refs.get(ref);
763
- }
764
- set(ref, value) {
765
- this.refs.set(ref, value);
766
- }
767
- delete(ref) {
768
- this.refs.delete(ref);
769
- }
770
- clear() {
771
- this.refs.clear();
772
- }
773
- size() {
774
- return this.refs.size;
775
- }
776
- };
777
- var ProgramBuilder = class {
778
- nodes = [];
779
- registry = new HostRegistry();
780
- compile(effect) {
781
- const root = this.visit(effect);
782
- return {
783
- program: {
784
- version: 1,
785
- root,
786
- nodes: this.nodes
787
- },
788
- registry: this.registry
789
- };
790
- }
791
- append(effect) {
792
- const previousNodes = this.nodes.length;
793
- const root = this.visit(effect);
794
- return {
795
- root,
796
- nodes: this.nodes.slice(previousNodes)
797
- };
798
- }
799
- add(node) {
800
- const id = this.nodes.length;
801
- this.nodes.push(node);
802
- return id;
803
- }
804
- visit(effect) {
805
- const current = effect;
806
- switch (current._tag) {
807
- case "Succeed":
808
- return this.add({ tag: "Succeed", valueRef: this.registry.register(current.value) });
809
- case "Fail":
810
- return this.add({ tag: "Fail", errorRef: this.registry.register(current.error) });
811
- case "Sync":
812
- return this.add({ tag: "Sync", fnRef: this.registry.register(current.thunk) });
813
- case "Async":
814
- return this.add({ tag: "Async", registerRef: this.registry.register(current.register) });
815
- case "FlatMap":
816
- return this.add({
817
- tag: "FlatMap",
818
- first: this.visit(current.first),
819
- fnRef: this.registry.register(current.andThen)
820
- });
821
- case "Fold":
822
- return this.add({
823
- tag: "Fold",
824
- first: this.visit(current.first),
825
- onFailureRef: this.registry.register(current.onFailure),
826
- onSuccessRef: this.registry.register(current.onSuccess)
827
- });
828
- case "Fork": {
829
- const base = {
830
- tag: "Fork",
831
- effectRef: this.registry.register(current.effect)
832
- };
833
- return this.add(current.scopeId === void 0 ? base : { ...base, scopeId: current.scopeId });
834
- }
835
- case "HostAction": {
836
- const base = {
837
- tag: "HostAction",
838
- actionRef: this.registry.register(current.action)
839
- };
840
- return this.add(current.decode === void 0 ? base : { ...base, decodeRef: this.registry.register(current.decode) });
841
- }
842
- default:
843
- return this.add({ tag: "Fail", errorRef: this.registry.register(new Error(`Unknown Async opcode: ${current?._tag}`)) });
844
- }
845
- }
846
- };
847
-
848
- // src/core/runtime/engine/FiberHandleImpl.ts
849
- var EngineFiberHandle = class {
850
- constructor(id, runtime, onScheduledStep, onInterrupt, onJoiner, onQueued) {
851
- this.onScheduledStep = onScheduledStep;
852
- this.onInterrupt = onInterrupt;
853
- this.onJoiner = onJoiner;
854
- this.onQueued = onQueued;
855
- this.id = id;
856
- this.runtime = runtime;
857
- }
858
- onScheduledStep;
859
- onInterrupt;
860
- onJoiner;
861
- onQueued;
862
- id;
863
- runtime;
864
- fiberContext;
865
- name;
866
- scopeId;
867
- parentFiberId;
868
- result = null;
869
- joiners = [];
870
- finalizers = [];
871
- finalizersDrained = false;
872
- internalStatus = "running";
873
- queued = false;
874
- status() {
875
- if (this.result == null) return "Running";
876
- if (this.result._tag === "Failure" && this.result.cause._tag === "Interrupt") return "Interrupted";
877
- return "Done";
878
- }
879
- engineStatus() {
880
- return this.internalStatus;
881
- }
882
- setEngineStatus(status) {
883
- this.internalStatus = status;
884
- }
885
- join(cb) {
886
- if (this.result != null) cb(this.result);
887
- else {
888
- this.onJoiner?.(this.id);
889
- this.joiners.push(cb);
890
- }
891
- }
892
- interrupt() {
893
- if (this.result != null) return;
894
- this.onInterrupt(this.id, Cause.interrupt());
895
- }
896
- addFinalizer(f) {
897
- this.finalizers.push(f);
898
- }
899
- schedule(tag = "step") {
900
- if (this.result != null || this.queued) return;
901
- this.queued = true;
902
- this.internalStatus = "queued";
903
- this.onQueued?.(this.id);
904
- this.runtime.scheduler.schedule(() => {
905
- this.queued = false;
906
- if (this.result != null) return;
907
- this.onScheduledStep(this.id);
908
- }, `wasm-fiber#${this.id}.${tag}`);
909
- }
910
- emit(ev) {
911
- this.runtime.hooks.emit(ev, {
912
- fiberId: this.id,
913
- scopeId: this.scopeId,
914
- traceId: this.fiberContext?.trace?.traceId,
915
- spanId: this.fiberContext?.trace?.spanId
916
- });
917
- }
918
- succeed(value) {
919
- this.complete(Exit.succeed(value));
920
- }
921
- fail(error) {
922
- this.complete(Exit.failCause(Cause.fail(error)));
923
- }
924
- die(defect) {
925
- this.complete(Exit.failCause(Cause.die(defect)));
926
- }
927
- interrupted() {
928
- this.complete(Exit.failCause(Cause.interrupt()));
929
- }
930
- complete(exit) {
931
- if (this.result != null) return;
932
- this.runFinalizersOnce(exit);
933
- this.result = exit;
934
- this.internalStatus = exit._tag === "Success" ? "done" : exit.cause._tag === "Interrupt" ? "interrupted" : "failed";
935
- const status = exit._tag === "Success" ? "success" : exit.cause._tag === "Interrupt" ? "interrupted" : "failure";
936
- this.emit({
937
- type: "fiber.end",
938
- fiberId: this.id,
939
- status,
940
- error: exit._tag === "Failure" ? exit.cause : void 0
941
- });
942
- for (const joiner of this.joiners) joiner(exit);
943
- this.joiners.length = 0;
944
- }
945
- runFinalizersOnce(exit) {
946
- if (this.finalizersDrained) return;
947
- this.finalizersDrained = true;
948
- while (this.finalizers.length > 0) {
949
- const finalizer = this.finalizers.pop();
950
- try {
951
- const eff = finalizer(exit);
952
- if (eff && typeof eff === "object" && "_tag" in eff) {
953
- this.runtime.fork(eff);
954
- }
955
- } catch {
956
- }
957
- }
958
- }
959
- };
960
-
961
- // src/core/runtime/engine/bridge/ReferenceWasmBridge.ts
962
- var ReferenceWasmBridge = class {
963
- kind = "wasm-reference";
964
- nextFiberId = 1;
965
- fibers = /* @__PURE__ */ new Map();
966
- started = 0;
967
- completed = 0;
968
- failed = 0;
969
- interrupted = 0;
970
- createFiber(program) {
971
- const id = this.nextFiberId++;
972
- this.started += 1;
973
- this.fibers.set(id, {
974
- id,
975
- program: cloneProgram(program),
976
- current: program.root,
977
- stack: [],
978
- status: "running",
979
- lastEvent: void 0
980
- });
981
- return id;
982
- }
983
- poll(fiberId) {
984
- const fiber = this.mustFiber(fiberId);
985
- if (fiber.status === "suspended" && fiber.lastEvent) return fiber.lastEvent;
986
- return this.step(fiber);
987
- }
988
- provideValue(fiberId, valueRef) {
989
- const fiber = this.mustFiber(fiberId);
990
- fiber.status = "running";
991
- fiber.lastEvent = void 0;
992
- return this.success(fiber, valueRef);
993
- }
994
- provideError(fiberId, errorRef) {
995
- const fiber = this.mustFiber(fiberId);
996
- fiber.status = "running";
997
- fiber.lastEvent = void 0;
998
- return this.failure(fiber, errorRef);
999
- }
1000
- provideEffect(fiberId, root, nodes) {
1001
- const fiber = this.mustFiber(fiberId);
1002
- fiber.status = "running";
1003
- fiber.lastEvent = void 0;
1004
- fiber.program.nodes.push(...nodes.map((node) => ({ ...node })));
1005
- fiber.current = root;
1006
- return this.step(fiber);
1007
- }
1008
- interrupt(fiberId, reasonRef) {
1009
- const fiber = this.mustFiber(fiberId);
1010
- fiber.status = "interrupted";
1011
- fiber.current = void 0;
1012
- fiber.stack = [];
1013
- this.interrupted += 1;
1014
- const event = { kind: "Interrupted", fiberId, reasonRef };
1015
- fiber.lastEvent = event;
1016
- return event;
1017
- }
1018
- dropFiber(fiberId) {
1019
- this.fibers.delete(fiberId);
1020
- }
1021
- stats() {
1022
- let running = 0;
1023
- let suspended = 0;
1024
- for (const fiber of this.fibers.values()) {
1025
- if (fiber.status === "running") running += 1;
1026
- if (fiber.status === "suspended") suspended += 1;
1027
- }
1028
- return {
1029
- started: this.started,
1030
- live: this.fibers.size,
1031
- running,
1032
- suspended,
1033
- completed: this.completed,
1034
- failed: this.failed,
1035
- interrupted: this.interrupted
1036
- };
1037
- }
1038
- mustFiber(fiberId) {
1039
- const fiber = this.fibers.get(fiberId);
1040
- if (!fiber) throw new Error(`Fiber ${fiberId} not found`);
1041
- return fiber;
1042
- }
1043
- step(fiber) {
1044
- while (true) {
1045
- if (fiber.status === "interrupted") {
1046
- const event = fiber.lastEvent ?? { kind: "Interrupted", fiberId: fiber.id, reasonRef: 0 };
1047
- fiber.lastEvent = event;
1048
- return event;
1049
- }
1050
- if (fiber.current === void 0) return this.markFailed(fiber, 0);
1051
- const node = fiber.program.nodes[fiber.current];
1052
- if (!node) return this.markFailed(fiber, 0);
1053
- switch (node.tag) {
1054
- case "Succeed":
1055
- fiber.current = void 0;
1056
- return this.success(fiber, node.valueRef);
1057
- case "Fail":
1058
- fiber.current = void 0;
1059
- return this.failure(fiber, node.errorRef);
1060
- case "Sync":
1061
- return this.suspend(fiber, { kind: "InvokeSync", fiberId: fiber.id, fnRef: node.fnRef });
1062
- case "Async":
1063
- return this.suspend(fiber, { kind: "InvokeAsync", fiberId: fiber.id, registerRef: node.registerRef });
1064
- case "FlatMap":
1065
- fiber.stack.push({ tag: "SuccessCont", fnRef: node.fnRef });
1066
- fiber.current = node.first;
1067
- continue;
1068
- case "Fold":
1069
- fiber.stack.push({ tag: "FoldCont", onFailureRef: node.onFailureRef, onSuccessRef: node.onSuccessRef });
1070
- fiber.current = node.first;
1071
- continue;
1072
- case "Fork": {
1073
- const event = node.scopeId === void 0 ? { kind: "InvokeFork", fiberId: fiber.id, effectRef: node.effectRef } : { kind: "InvokeFork", fiberId: fiber.id, effectRef: node.effectRef, scopeId: node.scopeId };
1074
- return this.suspend(fiber, event);
1075
- }
1076
- case "HostAction": {
1077
- const event = node.decodeRef === void 0 ? { kind: "InvokeHostAction", fiberId: fiber.id, actionRef: node.actionRef } : { kind: "InvokeHostAction", fiberId: fiber.id, actionRef: node.actionRef, decodeRef: node.decodeRef };
1078
- return this.suspend(fiber, event);
1079
- }
1080
- }
1081
- }
1082
- }
1083
- success(fiber, valueRef) {
1084
- const frame = fiber.stack.pop();
1085
- if (!frame) return this.markDone(fiber, valueRef);
1086
- if (frame.tag === "SuccessCont") {
1087
- return this.suspend(fiber, { kind: "InvokeFlatMap", fiberId: fiber.id, fnRef: frame.fnRef, valueRef });
1088
- }
1089
- return this.suspend(fiber, { kind: "InvokeFoldSuccess", fiberId: fiber.id, fnRef: frame.onSuccessRef, valueRef });
1090
- }
1091
- failure(fiber, errorRef) {
1092
- while (fiber.stack.length > 0) {
1093
- const frame = fiber.stack.pop();
1094
- if (frame.tag === "FoldCont") {
1095
- return this.suspend(fiber, { kind: "InvokeFoldFailure", fiberId: fiber.id, fnRef: frame.onFailureRef, errorRef });
1096
- }
1097
- }
1098
- return this.markFailed(fiber, errorRef);
1099
- }
1100
- suspend(fiber, event) {
1101
- fiber.status = "suspended";
1102
- fiber.lastEvent = event;
1103
- return event;
1104
- }
1105
- markDone(fiber, valueRef) {
1106
- fiber.status = "done";
1107
- fiber.current = void 0;
1108
- this.completed += 1;
1109
- const event = { kind: "Done", fiberId: fiber.id, valueRef };
1110
- fiber.lastEvent = event;
1111
- return event;
1112
- }
1113
- markFailed(fiber, errorRef) {
1114
- fiber.status = "failed";
1115
- fiber.current = void 0;
1116
- this.failed += 1;
1117
- const event = { kind: "Failed", fiberId: fiber.id, errorRef };
1118
- fiber.lastEvent = event;
1119
- return event;
1120
- }
1121
- };
1122
- function cloneProgram(program) {
1123
- return {
1124
- version: program.version,
1125
- root: program.root,
1126
- nodes: program.nodes.map((node) => ({ ...node }))
1127
- };
1128
- }
1129
-
1130
- // src/core/runtime/engine/bridge/WasmPackFiberBridge.ts
1131
- var WasmPackFiberBridge = class {
1132
- kind = "wasm";
1133
- vm;
1134
- constructor(modulePath) {
1135
- const mod = loadWasmModule(modulePath);
1136
- this.vm = new mod.BrassWasmVm();
1137
- }
1138
- createFiber(program) {
1139
- return this.vm.create_fiber(JSON.stringify(program));
1140
- }
1141
- poll(fiberId) {
1142
- return JSON.parse(this.vm.poll(fiberId));
1143
- }
1144
- provideValue(fiberId, valueRef) {
1145
- return JSON.parse(this.vm.provide_value(fiberId, valueRef));
1146
- }
1147
- provideError(fiberId, errorRef) {
1148
- return JSON.parse(this.vm.provide_error(fiberId, errorRef));
1149
- }
1150
- provideEffect(fiberId, root, nodes) {
1151
- return JSON.parse(this.vm.provide_effect(fiberId, root, JSON.stringify(nodes)));
1152
- }
1153
- interrupt(fiberId, reasonRef) {
1154
- return JSON.parse(this.vm.interrupt(fiberId, reasonRef));
1155
- }
1156
- dropFiber(fiberId) {
1157
- this.vm.drop_fiber(fiberId);
1158
- }
1159
- stats() {
1160
- return JSON.parse(this.vm.stats_json());
1161
- }
1162
- };
1163
- function loadWasmModule(modulePath) {
1164
- const mod = resolveWasmModule({ modulePath });
1165
- if (mod) return mod;
1166
- const errors = wasmModuleResolutionErrors();
1167
- throw new Error([
1168
- "engine='wasm' could not load wasm/pkg/brass_runtime_wasm_engine.js.",
1169
- "Run `npm run build:wasm` first and make sure wasm/pkg is present in the package.",
1170
- "For Node 18 + webpack, keep brass-runtime's wasm/pkg files available at runtime or externalize brass-runtime.",
1171
- ...errors.map((error) => `- ${error}`)
1172
- ].join("\n"));
1173
- }
1174
-
1175
- // src/core/runtime/engine/bridge/WasmFiberRegistryBridge.ts
1176
- var FIBER_STATE_QUEUED = 0;
1177
- var FIBER_STATE_RUNNING = 1;
1178
- var FIBER_STATE_SUSPENDED = 2;
1179
- var FIBER_STATE_DONE = 3;
1180
- var FIBER_STATE_FAILED = 4;
1181
- var FIBER_STATE_INTERRUPTED = 5;
1182
- var WasmFiberRegistryBridge = class {
1183
- registry;
1184
- constructor() {
1185
- const mod = resolveWasmModule();
1186
- const Ctor = mod?.BrassWasmFiberRegistry;
1187
- if (!Ctor) {
1188
- throw new Error("brass-runtime wasm fiber registry is not available. Run npm run build:wasm first.");
1189
- }
1190
- this.registry = new Ctor();
1191
- }
1192
- registerFiber(fiberId, parentId, scopeId) {
1193
- this.registry.register_fiber(fiberId, parentId ?? 0, scopeId ?? 0, Date.now());
1194
- }
1195
- markQueued(fiberId) {
1196
- this.registry.mark_queued(fiberId, Date.now());
1197
- }
1198
- markRunning(fiberId) {
1199
- this.registry.mark_running(fiberId, Date.now());
1200
- }
1201
- markSuspended(fiberId) {
1202
- this.registry.mark_suspended(fiberId, Date.now());
1203
- }
1204
- markDone(fiberId, status) {
1205
- return this.registry.mark_done(fiberId, statusToCode(status), Date.now());
1206
- }
1207
- dropFiber(fiberId) {
1208
- this.registry.drop_fiber(fiberId);
1209
- }
1210
- addJoiner(fiberId) {
1211
- this.registry.add_joiner(fiberId);
1212
- }
1213
- wake(fiberId) {
1214
- return this.registry.wake(fiberId);
1215
- }
1216
- drainWakeup() {
1217
- const id = this.registry.drain_wakeup();
1218
- return id === 0 ? void 0 : id;
1219
- }
1220
- drainWakeups() {
1221
- const ids = [];
1222
- for (; ; ) {
1223
- const id = this.drainWakeup();
1224
- if (id === void 0) return ids;
1225
- ids.push(id);
1226
- }
1227
- }
1228
- wakeQueueLength() {
1229
- return this.registry.wake_queue_len();
1230
- }
1231
- stateOf(fiberId) {
1232
- const code = this.registry.state_of(fiberId);
1233
- if (code === 4294967295) return "missing";
1234
- return codeToStatus(code);
1235
- }
1236
- stats() {
1237
- return JSON.parse(this.registry.stats_json());
1238
- }
1239
- };
1240
- function statusToCode(status) {
1241
- switch (status) {
1242
- case "queued":
1243
- return FIBER_STATE_QUEUED;
1244
- case "running":
1245
- return FIBER_STATE_RUNNING;
1246
- case "suspended":
1247
- return FIBER_STATE_SUSPENDED;
1248
- case "done":
1249
- return FIBER_STATE_DONE;
1250
- case "failed":
1251
- return FIBER_STATE_FAILED;
1252
- case "interrupted":
1253
- return FIBER_STATE_INTERRUPTED;
1254
- }
1255
- }
1256
- function codeToStatus(code) {
1257
- switch (code) {
1258
- case FIBER_STATE_QUEUED:
1259
- return "queued";
1260
- case FIBER_STATE_RUNNING:
1261
- return "running";
1262
- case FIBER_STATE_SUSPENDED:
1263
- return "suspended";
1264
- case FIBER_STATE_DONE:
1265
- return "done";
1266
- case FIBER_STATE_FAILED:
1267
- return "failed";
1268
- case FIBER_STATE_INTERRUPTED:
1269
- return "interrupted";
1270
- default:
1271
- return "missing";
1272
- }
1273
- }
1274
-
1275
- // src/core/runtime/engine/WasmFiberEngine.ts
1276
- var DEFAULT_BUDGET = 4096;
1277
- var WasmFiberEngine = class {
1278
- constructor(runtime, options = {}) {
1279
- this.runtime = runtime;
1280
- this.bridge = options.bridge ?? (options.reference ? new ReferenceWasmBridge() : new WasmPackFiberBridge(options.modulePath));
1281
- this.kind = this.bridge.kind;
1282
- this.fiberRegistry = this.kind === "wasm" ? new WasmFiberRegistryBridge() : void 0;
1283
- }
1284
- runtime;
1285
- kind;
1286
- bridge;
1287
- startedFibers = 0;
1288
- runningFibers = 0;
1289
- suspendedFibers = 0;
1290
- completedFibers = 0;
1291
- failedFibers = 0;
1292
- interruptedFibers = 0;
1293
- pendingHostEffects = 0;
1294
- states = /* @__PURE__ */ new Map();
1295
- fiberRegistry;
1296
- fork(effect, scopeId) {
1297
- const builder = new ProgramBuilder();
1298
- const compiled = builder.compile(effect);
1299
- const fiberId = this.bridge.createFiber(compiled.program);
1300
- const controller = new AbortController();
1301
- const handle = new EngineFiberHandle(
1302
- fiberId,
1303
- this.runtime,
1304
- (id) => this.scheduleWakeup(id),
1305
- (id, reason) => this.interruptById(id, reason),
1306
- (id) => this.fiberRegistry?.addJoiner(id),
1307
- (id) => this.fiberRegistry?.markQueued(id)
1308
- );
1309
- if (scopeId !== void 0) handle.scopeId = scopeId;
1310
- const state = {
1311
- fiberId,
1312
- handle,
1313
- builder,
1314
- registry: compiled.registry,
1315
- controller,
1316
- startedAt: Date.now(),
1317
- completed: false,
1318
- status: "running",
1319
- pendingCleanups: /* @__PURE__ */ new Set()
1320
- };
1321
- this.states.set(fiberId, state);
1322
- this.fiberRegistry?.registerFiber(fiberId, void 0, scopeId);
1323
- this.startedFibers += 1;
1324
- this.runningFibers += 1;
1325
- return handle;
1326
- }
1327
- stats() {
1328
- let hostRefs = 0;
1329
- for (const state of this.states.values()) hostRefs += state.registry.size();
1330
- return {
1331
- engine: this.kind,
1332
- startedFibers: this.startedFibers,
1333
- runningFibers: this.runningFibers,
1334
- suspendedFibers: this.suspendedFibers,
1335
- queuedFibers: 0,
1336
- completedFibers: this.completedFibers,
1337
- failedFibers: this.failedFibers,
1338
- interruptedFibers: this.interruptedFibers,
1339
- pendingHostEffects: this.pendingHostEffects,
1340
- hostRegistryRefs: hostRefs,
1341
- wasm: this.bridge.stats(),
1342
- fiberRegistry: this.fiberRegistry?.stats()
1343
- };
1344
- }
1345
- async shutdown() {
1346
- for (const state of Array.from(this.states.values())) {
1347
- this.interruptState(state, Cause.interrupt());
1348
- }
1349
- }
1350
- scheduleWakeup(fiberId) {
1351
- const state = this.states.get(fiberId);
1352
- if (!state || state.completed) return;
1353
- if (!this.fiberRegistry) {
1354
- this.driveById(fiberId);
1355
- return;
1356
- }
1357
- if (!this.fiberRegistry.wake(fiberId)) return;
1358
- this.drainWakeups();
1359
- }
1360
- drainWakeups() {
1361
- if (!this.fiberRegistry) return;
1362
- for (const fiberId of this.fiberRegistry.drainWakeups()) {
1363
- this.driveById(fiberId);
1364
- }
1365
- }
1366
- driveById(fiberId) {
1367
- const state = this.states.get(fiberId);
1368
- if (!state || state.completed) return;
1369
- this.fiberRegistry?.markRunning(fiberId);
1370
- withCurrentFiber(state.handle, () => this.drive(state));
1371
- }
1372
- drive(state, initialEvent) {
1373
- if (state.completed) return;
1374
- let budget = DEFAULT_BUDGET;
1375
- let event = initialEvent ?? this.bridge.poll(state.fiberId);
1376
- state.status = "running";
1377
- state.handle.setEngineStatus("running");
1378
- while (!state.completed && budget-- > 0) {
1379
- try {
1380
- switch (event.kind) {
1381
- case "Continue":
1382
- event = this.bridge.poll(state.fiberId);
1383
- continue;
1384
- case "Done": {
1385
- const value = state.registry.get(event.valueRef);
1386
- this.completeSuccess(state, value);
1387
- return;
1388
- }
1389
- case "Failed": {
1390
- const error = event.errorRef === 0 ? new Error("WASM fiber failed") : state.registry.get(event.errorRef);
1391
- this.completeFailure(state, error);
1392
- return;
1393
- }
1394
- case "Interrupted": {
1395
- this.completeInterrupted(state);
1396
- return;
1397
- }
1398
- case "InvokeSync": {
1399
- const fn = state.registry.get(event.fnRef);
1400
- try {
1401
- const valueRef = state.registry.register(fn(this.runtime.env));
1402
- event = this.bridge.provideValue(state.fiberId, valueRef);
1403
- } catch (error) {
1404
- event = this.bridge.provideError(state.fiberId, state.registry.register(error));
1405
- }
1406
- continue;
1407
- }
1408
- case "InvokeFlatMap": {
1409
- const fn = state.registry.get(event.fnRef);
1410
- const value = state.registry.get(event.valueRef);
1411
- try {
1412
- const next = fn(value);
1413
- const patch = state.builder.append(next);
1414
- event = this.bridge.provideEffect(state.fiberId, patch.root, patch.nodes);
1415
- } catch (error) {
1416
- event = this.bridge.provideError(state.fiberId, state.registry.register(error));
1417
- }
1418
- continue;
1419
- }
1420
- case "InvokeFoldFailure": {
1421
- const fn = state.registry.get(event.fnRef);
1422
- const errorValue = state.registry.get(event.errorRef);
1423
- try {
1424
- const next = fn(errorValue);
1425
- const patch = state.builder.append(next);
1426
- event = this.bridge.provideEffect(state.fiberId, patch.root, patch.nodes);
1427
- } catch (error) {
1428
- event = this.bridge.provideError(state.fiberId, state.registry.register(error));
1429
- }
1430
- continue;
1431
- }
1432
- case "InvokeFoldSuccess": {
1433
- const fn = state.registry.get(event.fnRef);
1434
- const value = state.registry.get(event.valueRef);
1435
- try {
1436
- const next = fn(value);
1437
- const patch = state.builder.append(next);
1438
- event = this.bridge.provideEffect(state.fiberId, patch.root, patch.nodes);
1439
- } catch (error) {
1440
- event = this.bridge.provideError(state.fiberId, state.registry.register(error));
1441
- }
1442
- continue;
1443
- }
1444
- case "InvokeFork": {
1445
- const effect = state.registry.get(event.effectRef);
1446
- try {
1447
- const child = this.runtime.fork(effect, event.scopeId);
1448
- event = this.bridge.provideValue(state.fiberId, state.registry.register(child));
1449
- } catch (error) {
1450
- event = this.bridge.provideError(state.fiberId, state.registry.register(error));
1451
- }
1452
- continue;
1453
- }
1454
- case "InvokeAsync": {
1455
- this.scheduleAsync(state, event.registerRef);
1456
- return;
1457
- }
1458
- case "InvokeHostAction": {
1459
- this.scheduleHostAction(state, event.actionRef, event.decodeRef);
1460
- return;
1461
- }
1462
- }
1463
- } catch (error) {
1464
- event = this.bridge.provideError(state.fiberId, state.registry.register(error));
1465
- }
1466
- }
1467
- if (!state.completed) state.handle.schedule("budget-yield");
1468
- }
1469
- scheduleAsync(state, registerRef) {
1470
- this.markSuspended(state, "async");
1471
- this.pendingHostEffects += 1;
1472
- const register = state.registry.get(registerRef);
1473
- let done = false;
1474
- let asyncRegistered = false;
1475
- let syncExit = null;
1476
- const cleanup = () => {
1477
- done = true;
1478
- state.pendingCleanups.delete(cleanup);
1479
- };
1480
- state.pendingCleanups.add(cleanup);
1481
- const cb = (exitLike) => {
1482
- if (done) return;
1483
- const exit = exitLike;
1484
- if (!asyncRegistered) {
1485
- syncExit = exit;
1486
- return;
1487
- }
1488
- cleanup();
1489
- this.pendingHostEffects = Math.max(0, this.pendingHostEffects - 1);
1490
- this.markRunning(state, "async");
1491
- this.resumeWithExit(state, exit);
1492
- };
1493
- try {
1494
- const canceler = register(this.runtime.env, cb);
1495
- asyncRegistered = true;
1496
- if (syncExit) {
1497
- cleanup();
1498
- this.pendingHostEffects = Math.max(0, this.pendingHostEffects - 1);
1499
- this.markRunning(state, "async-sync");
1500
- this.resumeWithExit(state, syncExit);
1501
- return;
1502
- }
1503
- if (typeof canceler === "function") {
1504
- const cancelCleanup = () => {
1505
- if (done) return;
1506
- done = true;
1507
- try {
1508
- canceler();
1509
- } catch {
1510
- }
1511
- state.pendingCleanups.delete(cancelCleanup);
1512
- };
1513
- state.pendingCleanups.add(cancelCleanup);
1514
- state.handle.addFinalizer(() => cancelCleanup());
1515
- }
1516
- } catch (error) {
1517
- cleanup();
1518
- this.pendingHostEffects = Math.max(0, this.pendingHostEffects - 1);
1519
- this.markRunning(state, "async-register-error");
1520
- this.resumeWithError(state, error);
1521
- }
1522
- }
1523
- scheduleHostAction(state, actionRef, decodeRef) {
1524
- this.markSuspended(state, "host-action");
1525
- this.pendingHostEffects += 1;
1526
- const action = state.registry.get(actionRef);
1527
- const startedAt = Date.now();
1528
- const cleanup = () => {
1529
- state.pendingCleanups.delete(cleanup);
1530
- };
1531
- state.pendingCleanups.add(cleanup);
1532
- this.runtime.hostExecutor.execute(action, {
1533
- fiberId: state.fiberId,
1534
- env: this.runtime.env,
1535
- signal: state.controller.signal,
1536
- deadlineAt: action.timeoutMs === void 0 ? void 0 : Date.now() + action.timeoutMs
1537
- }).then((result) => {
1538
- cleanup();
1539
- if (state.completed) return;
1540
- this.pendingHostEffects = Math.max(0, this.pendingHostEffects - 1);
1541
- this.markRunning(state, "host-action");
1542
- try {
1543
- if (decodeRef !== void 0) {
1544
- const decode = state.registry.get(decodeRef);
1545
- this.resumeWithValue(state, decode(result));
1546
- return;
1547
- }
1548
- if (result.kind === "error") {
1549
- this.resumeWithError(state, result.error);
1550
- return;
1551
- }
1552
- this.resumeWithValue(state, result.value);
1553
- } catch (error) {
1554
- this.resumeWithError(state, error);
1555
- }
1556
- }).catch((error) => {
1557
- cleanup();
1558
- if (state.completed) return;
1559
- this.pendingHostEffects = Math.max(0, this.pendingHostEffects - 1);
1560
- this.markRunning(state, "host-action-error");
1561
- this.resumeWithError(state, error);
1562
- });
1563
- }
1564
- resumeWithExit(state, exit) {
1565
- if (state.completed) return;
1566
- if (exit._tag === "Success") {
1567
- this.resumeWithValue(state, exit.value);
1568
- return;
1569
- }
1570
- const cause = exit.cause;
1571
- if (cause._tag === "Interrupt") {
1572
- this.interruptState(state, cause);
1573
- return;
1574
- }
1575
- if (cause._tag === "Fail") {
1576
- this.resumeWithError(state, cause.error);
1577
- return;
1578
- }
1579
- this.completeDie(state, cause.defect);
1580
- }
1581
- resumeWithValue(state, value) {
1582
- const event = this.bridge.provideValue(state.fiberId, state.registry.register(value));
1583
- this.runtime.scheduler.schedule(() => withCurrentFiber(state.handle, () => this.drive(state, event)), `wasm-fiber#${state.fiberId}.resume`);
1584
- }
1585
- resumeWithError(state, error) {
1586
- const event = this.bridge.provideError(state.fiberId, state.registry.register(error));
1587
- this.runtime.scheduler.schedule(() => withCurrentFiber(state.handle, () => this.drive(state, event)), `wasm-fiber#${state.fiberId}.resume-error`);
1588
- }
1589
- interruptById(fiberId, reason) {
1590
- const state = this.states.get(fiberId);
1591
- if (!state) return;
1592
- this.interruptState(state, reason);
1593
- }
1594
- interruptState(state, reason) {
1595
- if (state.completed) return;
1596
- if (!state.controller.signal.aborted) state.controller.abort(reason);
1597
- for (const cleanup of Array.from(state.pendingCleanups)) cleanup();
1598
- const event = this.bridge.interrupt(state.fiberId, state.registry.register(reason));
1599
- this.drive(state, event);
1600
- }
1601
- markSuspended(state, reason) {
1602
- if (state.status !== "suspended") {
1603
- this.suspendedFibers += 1;
1604
- state.status = "suspended";
1605
- this.fiberRegistry?.markSuspended(state.fiberId);
1606
- state.handle.setEngineStatus("suspended");
1607
- state.handle.emit({ type: "fiber.suspend", fiberId: state.fiberId, reason });
1608
- }
1609
- }
1610
- markRunning(state, _reason) {
1611
- if (state.status === "suspended") {
1612
- this.suspendedFibers = Math.max(0, this.suspendedFibers - 1);
1613
- state.status = "running";
1614
- this.fiberRegistry?.markRunning(state.fiberId);
1615
- state.handle.setEngineStatus("running");
1616
- state.handle.emit({ type: "fiber.resume", fiberId: state.fiberId });
1617
- }
1618
- }
1619
- completeSuccess(state, value) {
1620
- if (state.completed) return;
1621
- state.completed = true;
1622
- state.status = "done";
1623
- this.fiberRegistry?.markDone(state.fiberId, "done");
1624
- this.completedFibers += 1;
1625
- this.cleanupState(state);
1626
- state.handle.succeed(value);
1627
- }
1628
- completeFailure(state, error) {
1629
- if (state.completed) return;
1630
- state.completed = true;
1631
- state.status = "failed";
1632
- this.fiberRegistry?.markDone(state.fiberId, "failed");
1633
- this.failedFibers += 1;
1634
- this.cleanupState(state);
1635
- state.handle.fail(error);
1636
- }
1637
- completeDie(state, defect) {
1638
- if (state.completed) return;
1639
- state.completed = true;
1640
- state.status = "failed";
1641
- this.fiberRegistry?.markDone(state.fiberId, "failed");
1642
- this.failedFibers += 1;
1643
- this.cleanupState(state);
1644
- state.handle.die(defect);
1645
- }
1646
- completeInterrupted(state) {
1647
- if (state.completed) return;
1648
- state.completed = true;
1649
- state.status = "interrupted";
1650
- this.fiberRegistry?.markDone(state.fiberId, "interrupted");
1651
- this.interruptedFibers += 1;
1652
- this.cleanupState(state);
1653
- state.handle.interrupted();
1654
- }
1655
- cleanupState(state) {
1656
- this.runningFibers = Math.max(0, this.runningFibers - 1);
1657
- if (state.status === "suspended") this.suspendedFibers = Math.max(0, this.suspendedFibers - 1);
1658
- for (const cleanup of Array.from(state.pendingCleanups)) cleanup();
1659
- state.pendingCleanups.clear();
1660
- this.bridge.dropFiber(state.fiberId);
1661
- this.fiberRegistry?.dropFiber(state.fiberId);
1662
- state.registry.clear();
1663
- this.states.delete(state.fiberId);
1664
- }
1665
- };
1666
-
1667
- // src/core/runtime/capabilities.ts
1668
- function runtimeCapabilities() {
1669
- const mod = resolveWasmModule();
1670
- return {
1671
- wasmAvailable: !!mod,
1672
- wasmFiberEngine: typeof mod?.BrassWasmVm === "function",
1673
- wasmRingBuffer: typeof mod?.BrassWasmRingBuffer === "function",
1674
- wasmScheduler: typeof mod?.BrassWasmSchedulerStateMachine === "function",
1675
- wasmFiberRegistry: typeof mod?.BrassWasmFiberRegistry === "function",
1676
- wasmStreamChunks: typeof mod?.BrassWasmChunkBuffer === "function"
1677
- };
1678
- }
1679
-
1680
- // src/core/runtime/runtime.ts
1681
- var NoopHooks = {
1682
- emit() {
1683
- }
1684
- };
1685
- var Runtime = class _Runtime {
1686
- env;
1687
- scheduler;
1688
- hooks;
1689
- hostExecutor;
1690
- engineMode;
1691
- wasmOptions;
1692
- fiberEngine;
1693
- fallbackUsed;
1694
- forkPolicy;
1695
- // opcional: registry para observabilidad
1696
- registry;
1697
- constructor(args) {
1698
- this.env = args.env;
1699
- this.scheduler = args.scheduler ?? globalScheduler;
1700
- this.hooks = args.hooks ?? NoopHooks;
1701
- this.hostExecutor = args.hostExecutor ?? DefaultHostExecutor;
1702
- this.engineMode = args.engine ?? "auto";
1703
- this.wasmOptions = args.wasm;
1704
- this.forkPolicy = makeForkPolicy(this.env, this.hooks);
1705
- const selected = this.makeFiberEngine(this.engineMode, args.wasm);
1706
- this.fiberEngine = selected.engine;
1707
- this.fallbackUsed = selected.fallbackUsed;
1708
- }
1709
- makeFiberEngine(mode, wasm) {
1710
- if (mode === "js") return { engine: new JsFiberEngine(this), fallbackUsed: false };
1711
- if (mode === "wasm-reference") return { engine: new WasmFiberEngine(this, { ...wasm, reference: true }), fallbackUsed: false };
1712
- if (mode === "wasm") return { engine: new WasmFiberEngine(this, wasm), fallbackUsed: false };
1713
- try {
1714
- const capabilities = runtimeCapabilities();
1715
- if (capabilities.wasmFiberEngine) {
1716
- return { engine: new WasmFiberEngine(this, wasm), fallbackUsed: false };
1717
- }
1718
- } catch {
1719
- }
1720
- return { engine: new JsFiberEngine(this), fallbackUsed: true };
1721
- }
1722
- /** Returns true when the runtime has real hooks (not the no-op singleton). */
1723
- hasActiveHooks() {
1724
- return this.hooks !== NoopHooks;
1725
- }
1726
- /** Deriva un runtime con env extendido (estilo provide/locally) */
1727
- provide(env) {
1728
- return new _Runtime({
1729
- env: Object.assign({}, this.env, env),
1730
- scheduler: this.scheduler,
1731
- hooks: this.hooks,
1732
- engine: this.engineMode,
1733
- hostExecutor: this.hostExecutor,
1734
- wasm: this.wasmOptions
1735
- });
1736
- }
1737
- emit(ev) {
1738
- if (this.hooks === NoopHooks) return;
1739
- const f = getCurrentFiber();
1740
- const ctx = {
1741
- fiberId: f?.id,
1742
- scopeId: f?.scopeId,
1743
- // ✅ FIX: era f?.scope
1744
- traceId: f?.fiberContext?.trace?.traceId,
1745
- spanId: f?.fiberContext?.trace?.spanId
1746
- };
1747
- this.hooks.emit(ev, ctx);
1748
- }
1749
- /**
1750
- * ✅ CAMBIO: fork(effect, scopeId?) y pasa scopeId a forkPolicy
1751
- */
1752
- fork(effect, scopeId) {
1753
- const parent = getCurrentFiber();
1754
- const fiber = this.fiberEngine.fork(effect, scopeId);
1755
- if (scopeId !== void 0) fiber.scopeId = scopeId;
1756
- this.forkPolicy.initChild(fiber, parent, scopeId);
1757
- fiber.schedule?.("initial-step");
1758
- return fiber;
1759
- }
1760
- stats() {
1761
- const data = this.fiberEngine.stats();
1762
- const engine = this.fiberEngine.kind === "js" ? "js" : "wasm";
1763
- return { engine, fallbackUsed: this.fallbackUsed, data };
1764
- }
1765
- capabilities() {
1766
- return runtimeCapabilities();
1767
- }
1768
- shutdown() {
1769
- return this.fiberEngine.shutdown?.();
1770
- }
1771
- unsafeRunAsync(effect, cb) {
1772
- const fiber = this.fork(effect);
1773
- fiber.join(cb);
1774
- }
1775
- toPromise(effect) {
1776
- return new Promise((resolve, reject) => {
1777
- const fiber = this.fork(effect);
1778
- fiber.join((exit) => {
1779
- if (exit._tag === "Success") resolve(exit.value);
1780
- else {
1781
- const c = exit.cause;
1782
- if (c?._tag === "Fail") reject(c.error);
1783
- else reject(new Error("Interrupted"));
1784
- }
1785
- });
1786
- });
1787
- }
1788
- // helper: correr un efecto y “tirar” el resultado
1789
- unsafeRun(effect) {
1790
- this.unsafeRunAsync(effect, () => {
1791
- });
1792
- }
1793
- delay(ms, eff) {
1794
- return async((_env, cb) => {
1795
- const handle = setTimeout(() => {
1796
- this.unsafeRunAsync(eff, cb);
1797
- }, ms);
1798
- return () => clearTimeout(handle);
1799
- });
1800
- }
1801
- // util para crear runtime default
1802
- static make(env, scheduler = globalScheduler) {
1803
- return new _Runtime({ env, scheduler });
1804
- }
1805
- static makeWithEngine(env, engine, options = {}) {
1806
- return new _Runtime({ ...options, env, engine });
1807
- }
1808
- /** Convenience logger: emits a RuntimeEvent of type "log". */
1809
- log(level, message, fields) {
1810
- this.emit({ type: "log", level, message, fields });
1811
- }
1812
- };
1813
- function fork(effect, env) {
1814
- return Runtime.make(env ?? {}).fork(effect);
1815
- }
1816
- function unsafeRunAsync(effect, env, cb) {
1817
- Runtime.make(env ?? {}).unsafeRunAsync(effect, cb);
1818
- }
1819
- function toPromise(effect, env) {
1820
- return Runtime.make(env ?? {}).toPromise(effect);
1821
- }
1822
- function fromPromiseAbortable(make, onReject) {
1823
- return {
1824
- _tag: "Async",
1825
- register: (env, cb) => {
1826
- const controller = new AbortController();
1827
- let done = false;
1828
- make(controller.signal, env).then((value) => {
1829
- if (done) return;
1830
- done = true;
1831
- cb(Exit.succeed(value));
1832
- }).catch((err) => {
1833
- if (done) return;
1834
- done = true;
1835
- cb(Exit.failCause(Cause.fail(onReject(err))));
1836
- });
1837
- return () => {
1838
- if (done) return;
1839
- done = true;
1840
- controller.abort();
1841
- cb(Exit.failCause(Cause.interrupt()));
1842
- };
1843
- }
1844
- };
1845
- }
1846
- function unsafeRunFoldWithEnv(eff, env, onFailure, onSuccess) {
1847
- unsafeRunAsync(eff, env, (ex) => {
1848
- if (ex._tag === "Failure") onFailure(ex.cause);
1849
- else onSuccess(ex.value);
1850
- });
1851
- }
1852
-
1853
- // src/core/runtime/fiber.ts
1854
- var _current = null;
1855
- var STEP = {
1856
- CONTINUE: "Continue",
1857
- SUSPEND: "Suspend",
1858
- DONE: "Done"
1859
- };
1860
- var RUN = {
1861
- QUEUED: "Queued",
1862
- RUNNING: "Running",
1863
- SUSPENDED: "Suspended",
1864
- DONE: "Done"
1865
- };
1866
- var nextId = 1;
1867
- var DEFAULT_BUDGET2 = 4096;
1868
- var __benchmarkBudget;
1869
- function setBenchmarkBudget(budget) {
1870
- __benchmarkBudget = budget;
1871
- }
1872
- function getBenchmarkBudget() {
1873
- return __benchmarkBudget;
1874
- }
1875
- function reassociateFlatMap(cur) {
1876
- let current = cur;
1877
- while (current._tag === "FlatMap" && current.first?._tag === "FlatMap") {
1878
- const inner = current.first;
1879
- const g = current.andThen;
1880
- current = {
1881
- _tag: "FlatMap",
1882
- first: inner.first,
1883
- andThen: (a) => ({
1884
- _tag: "FlatMap",
1885
- first: inner.andThen(a),
1886
- andThen: g
1887
- })
1888
- };
1889
- }
1890
- return current;
1891
- }
1892
- var RuntimeFiber = class {
1893
- id;
1894
- // 👇 CLAVE: guardar el runtime en el fiber (para getCurrentRuntime())
1895
- runtime;
1896
- closing = null;
1897
- finishing = false;
1898
- runState = RUN.RUNNING;
1899
- interrupted = false;
1900
- result = null;
1901
- joiners = [];
1902
- // estado de evaluación
1903
- current;
1904
- stack = [];
1905
- fiberFinalizers = [];
1906
- finalizersDrained = false;
1907
- fiberContext;
1908
- name;
1909
- scopeId;
1910
- /**
1911
- * Cached closure for the scheduler callback — avoids creating a new
1912
- * closure on every `schedule()` call. The tag parameter used by the
1913
- * scheduler is only part of the label string, not the callback logic,
1914
- * so a single cached closure is sufficient.
1915
- */
1916
- boundStep;
1917
- constructor(runtime, effect) {
1918
- this.id = nextId++;
1919
- this.runtime = runtime;
1920
- this.current = effect;
1921
- this.boundStep = () => {
1922
- withCurrentFiber(this, () => {
1923
- if (this.runState === RUN.DONE) return;
1924
- this.runState = RUN.RUNNING;
1925
- const decision = this.step();
1926
- switch (decision) {
1927
- case STEP.CONTINUE:
1928
- this.schedule("continue");
1929
- return;
1930
- case STEP.SUSPEND:
1931
- this.runState = RUN.SUSPENDED;
1932
- this.emit({ type: "fiber.suspend", fiberId: this.id });
1933
- return;
1934
- case STEP.DONE:
1935
- this.runState = RUN.DONE;
1936
- return;
1937
- }
1938
- });
1939
- };
1940
- }
1941
- // helpers para no tocar el resto del código
1942
- get env() {
1943
- return this.runtime.env;
1944
- }
1945
- get scheduler() {
1946
- return this.runtime.scheduler ?? globalScheduler;
1947
- }
1948
- emit(ev) {
1949
- this.runtime.hooks.emit(ev, {
1950
- fiberId: this.id,
1951
- scopeId: this.scopeId,
1952
- traceId: this.fiberContext?.trace?.traceId,
1953
- spanId: this.fiberContext?.trace?.spanId
1954
- });
1955
- }
1956
- addFinalizer(f) {
1957
- this.fiberFinalizers.push(f);
1958
- }
1959
- status() {
1960
- if (this.result == null) return "Running";
1961
- if (this.result._tag === "Failure" && this.result.cause._tag === "Interrupt") return "Interrupted";
1962
- return "Done";
1963
- }
1964
- join(cb) {
1965
- if (this.result != null) cb(this.result);
1966
- else this.joiners.push(cb);
1967
- }
1968
- interrupt() {
1969
- if (this.result != null) return;
1970
- if (this.interrupted) return;
1971
- this.interrupted = true;
1972
- this.schedule("interrupt-step");
1973
- }
1974
- schedule(tag = "step") {
1975
- if (this.runState === RUN.DONE || this.runState === RUN.QUEUED) return;
1976
- if (this.runState === RUN.SUSPENDED) {
1977
- this.emit({ type: "fiber.resume", fiberId: this.id });
1978
- }
1979
- this.runState = RUN.QUEUED;
1980
- this.scheduler.schedule(
1981
- this.boundStep,
1982
- `fiber#${this.id}.${tag}`
1983
- );
1984
- }
1985
- runFinalizersOnce(exit) {
1986
- if (this.finalizersDrained) return;
1987
- this.finalizersDrained = true;
1988
- while (this.fiberFinalizers.length > 0) {
1989
- const fin = this.fiberFinalizers.pop();
1990
- try {
1991
- const eff = fin(exit);
1992
- if (eff && typeof eff === "object" && "_tag" in eff) {
1993
- unsafeRunAsync(eff, this.env, () => {
1994
- });
1995
- }
1996
- } catch {
1997
- }
1998
- }
1999
- }
2000
- notify(exit) {
2001
- if (this.result != null) return;
2002
- if (this.closing != null) return;
2003
- this.finishing = true;
2004
- this.closing = exit;
2005
- this.runFinalizersOnce(exit);
2006
- this.result = exit;
2007
- const status = exit._tag === "Success" ? "success" : exit.cause._tag === "Interrupt" ? "interrupted" : "failure";
2008
- this.emit({
2009
- type: "fiber.end",
2010
- fiberId: this.id,
2011
- status,
2012
- error: exit._tag === "Failure" ? exit.cause : void 0
2013
- });
2014
- for (const j of this.joiners) j(exit);
2015
- this.joiners.length = 0;
2016
- }
2017
- onSuccess(value) {
2018
- const frame = this.stack.pop();
2019
- if (!frame) {
2020
- this.notify(Exit.succeed(value));
2021
- return;
2022
- }
2023
- if (frame._tag === "SuccessCont") {
2024
- try {
2025
- this.current = frame.k(value);
2026
- } catch (e) {
2027
- this.notify(Exit.failCause(Cause.die(e)));
2028
- }
2029
- return;
2030
- }
2031
- try {
2032
- this.current = frame.onSuccess(value);
2033
- } catch (e) {
2034
- this.notify(Exit.failCause(Cause.die(e)));
2035
- }
2036
- }
2037
- onFailure(error) {
2038
- while (this.stack.length > 0) {
2039
- const fr = this.stack.pop();
2040
- if (fr._tag === "FoldCont") {
2041
- try {
2042
- this.current = fr.onFailure(error);
2043
- return;
2044
- } catch (e) {
2045
- error = e;
2046
- continue;
2047
- }
2048
- }
2049
- }
2050
- this.notify(Exit.failCause(Cause.fail(error)));
2051
- }
2052
- budget = DEFAULT_BUDGET2;
2053
- step() {
2054
- if (this.result != null) return STEP.DONE;
2055
- if (this.interrupted) {
2056
- this.notify(Exit.failCause(Cause.interrupt()));
2057
- return STEP.DONE;
2058
- }
2059
- this.budget = __benchmarkBudget ?? DEFAULT_BUDGET2;
2060
- while (this.budget-- > 0) {
2061
- this.current = reassociateFlatMap(this.current);
2062
- const current = this.current;
2063
- switch (current._tag) {
2064
- case "Succeed": {
2065
- this.onSuccess(current.value);
2066
- break;
2067
- }
2068
- case "Fail": {
2069
- this.onFailure(current.error);
2070
- break;
2071
- }
2072
- case "FlatMap": {
2073
- this.stack.push({ _tag: "SuccessCont", k: current.andThen });
2074
- this.current = current.first;
2075
- break;
2076
- }
2077
- case "Fold": {
2078
- this.stack.push({
2079
- _tag: "FoldCont",
2080
- onFailure: current.onFailure,
2081
- onSuccess: current.onSuccess
2082
- });
2083
- this.current = current.first;
2084
- break;
2085
- }
2086
- case "Async": {
2087
- if (this.finishing) {
2088
- return this.result != null ? STEP.DONE : STEP.CONTINUE;
2089
- }
2090
- let done = false;
2091
- let asyncRegistered = false;
2092
- let syncResolved = false;
2093
- let syncExit = null;
2094
- const cb = (exit) => {
2095
- if (done) return;
2096
- done = true;
2097
- if (this.result != null || this.closing != null) return;
2098
- if (!asyncRegistered) {
2099
- syncResolved = true;
2100
- syncExit = exit;
2101
- return;
2102
- }
2103
- if (exit._tag === "Success") {
2104
- this.current = Async.succeed(exit.value);
2105
- this.schedule("async-resume");
2106
- return;
2107
- }
2108
- const cause = exit.cause;
2109
- if (cause._tag === "Interrupt") {
2110
- this.notify(Exit.failCause(Cause.interrupt()));
2111
- return;
2112
- }
2113
- if (cause._tag === "Fail") {
2114
- this.current = Async.fail(cause.error);
2115
- this.schedule("async-resume");
2116
- return;
2117
- }
2118
- this.notify(Exit.failCause(Cause.die(cause.defect)));
2119
- };
2120
- const canceler = current.register(this.env, cb);
2121
- asyncRegistered = true;
2122
- if (syncResolved && syncExit) {
2123
- const resolvedExit = syncExit;
2124
- if (resolvedExit._tag === "Success") {
2125
- this.onSuccess(resolvedExit.value);
2126
- } else {
2127
- const cause = resolvedExit.cause;
2128
- if (cause._tag === "Interrupt") {
2129
- this.notify(Exit.failCause(Cause.interrupt()));
2130
- } else if (cause._tag === "Fail") {
2131
- this.onFailure(cause.error);
2132
- } else {
2133
- this.notify(Exit.failCause(Cause.die(cause.defect)));
2134
- }
2135
- }
2136
- break;
2137
- }
2138
- if (typeof canceler === "function") {
2139
- this.addFinalizer(() => {
2140
- done = true;
2141
- try {
2142
- canceler();
2143
- } catch {
2144
- }
2145
- });
2146
- }
2147
- return STEP.SUSPEND;
2148
- }
2149
- case "Fork": {
2150
- const child = this.runtime.fork(current.effect, current.scopeId);
2151
- this.onSuccess(child);
2152
- break;
2153
- }
2154
- case "Sync": {
2155
- try {
2156
- const a = current.thunk(this.env);
2157
- this.onSuccess(a);
2158
- } catch (e) {
2159
- this.onFailure(e);
2160
- }
2161
- break;
2162
- }
2163
- default: {
2164
- this.onFailure(new Error(`Unknown opcode: ${current._tag}`));
2165
- return STEP.CONTINUE;
2166
- }
2167
- }
2168
- if (this.result != null) return STEP.DONE;
2169
- }
2170
- return STEP.CONTINUE;
2171
- }
2172
- };
2173
- function getCurrentFiber() {
2174
- return _current;
2175
- }
2176
- function unsafeGetCurrentRuntime() {
2177
- const f = getCurrentFiber();
2178
- if (!f?.runtime) {
2179
- throw new Error("unsafeGetCurrentRuntime: no current fiber/runtime");
2180
- }
2181
- return f.runtime;
2182
- }
2183
- function withCurrentFiber(fiber, f) {
2184
- const prev = _current;
2185
- _current = fiber;
2186
- try {
2187
- return f();
2188
- } finally {
2189
- _current = prev;
2190
- }
2191
- }
2192
-
2193
- // src/core/runtime/scope.ts
2194
- var nextScopeId = 1;
2195
- function awaitAll(fibers) {
2196
- return async((_env, cb) => {
2197
- let remaining = fibers.length;
2198
- if (remaining === 0) {
2199
- cb({ _tag: "Success", value: void 0 });
2200
- return;
2201
- }
2202
- for (const f of fibers) {
2203
- f.join(() => {
2204
- remaining -= 1;
2205
- if (remaining === 0) cb({ _tag: "Success", value: void 0 });
2206
- });
2207
- }
2208
- });
2209
- }
2210
- var Scope = class _Scope {
2211
- constructor(runtime, parentScopeId) {
2212
- this.runtime = runtime;
2213
- this.parentScopeId = parentScopeId;
2214
- this.id = nextScopeId++;
2215
- const inferredParent = this.parentScopeId ?? getCurrentFiber()?.scopeId;
2216
- if (this.runtime.hasActiveHooks()) {
2217
- this.runtime.emit({
2218
- type: "scope.open",
2219
- scopeId: this.id,
2220
- parentScopeId: inferredParent
2221
- });
2222
- }
2223
- }
2224
- runtime;
2225
- parentScopeId;
2226
- id;
2227
- closed = false;
2228
- children = /* @__PURE__ */ new Set();
2229
- subScopes = /* @__PURE__ */ new Set();
2230
- finalizers = [];
2231
- /** registra un finalizer (LIFO) */
2232
- addFinalizer(f) {
2233
- if (this.closed) {
2234
- throw new Error("Trying to add finalizer to closed scope");
2235
- }
2236
- this.finalizers.push(f);
2237
- }
2238
- /** crea un sub scope (mismo runtime) */
2239
- subScope() {
2240
- if (this.closed) throw new Error("Scope closed");
2241
- const s = new _Scope(this.runtime, this.id);
2242
- this.subScopes.add(s);
2243
- return s;
2244
- }
2245
- /** ✅ fork en este scope */
2246
- fork(eff) {
2247
- if (this.closed) throw new Error("Scope closed");
2248
- const f = this.runtime.fork(eff, this.id);
2249
- this.children.add(f);
2250
- f.join(() => this.children.delete(f));
2251
- return f;
2252
- }
2253
- /** close fire-and-forget (no bloquea) */
2254
- close(exit = { _tag: "Success", value: void 0 }) {
2255
- this.runtime.fork(this.closeAsync(exit));
2256
- }
2257
- /** Emit the scope.close event if hooks are active. */
2258
- emitCloseEvent(exit) {
2259
- if (this.runtime.hasActiveHooks()) {
2260
- const status = exit._tag === "Success" ? "success" : exit.cause._tag === "Interrupt" ? "interrupted" : "failure";
2261
- this.runtime.emit({
2262
- type: "scope.close",
2263
- scopeId: this.id,
2264
- status,
2265
- error: exit._tag === "Failure" && exit.cause._tag === "Fail" ? exit.cause.error : void 0
2266
- });
2267
- }
2268
- }
2269
- /**
2270
- * Build an effect that executes finalizers in LIFO order.
2271
- *
2272
- * Optimization over the original: instead of wrapping every finalizer in
2273
- * `asyncFold(fin(exit), () => unit(), () => unit())` which creates 3 effect
2274
- * nodes per finalizer (Fold + 2 Succeed), we use a single Sync thunk per
2275
- * finalizer that catches errors inline. When the finalizer returns a
2276
- * Succeed effect (like `unit()`), the Sync thunk completes without creating
2277
- * additional effect nodes.
2278
- */
2279
- buildFinalizerEffect(exit) {
2280
- const fins = this.finalizers;
2281
- if (fins.length === 0) return unit();
2282
- let chain = unit();
2283
- for (let i = fins.length - 1; i >= 0; i--) {
2284
- const fin = fins[i];
2285
- chain = asyncFlatMap(chain, () => {
2286
- let result;
2287
- try {
2288
- result = fin(exit);
2289
- } catch {
2290
- return unit();
2291
- }
2292
- if (result._tag === "Succeed") {
2293
- return unit();
2294
- }
2295
- return asyncFold(
2296
- result,
2297
- () => unit(),
2298
- () => unit()
2299
- );
2300
- });
2301
- }
2302
- return chain;
2303
- }
2304
- closeAsync(exit = { _tag: "Success", value: void 0 }, opts = { awaitChildren: true }) {
2305
- return asyncFlatMap(
2306
- unit(),
2307
- () => async((env, cb) => {
2308
- if (this.closed) {
2309
- cb({ _tag: "Success", value: void 0 });
2310
- return;
2311
- }
2312
- this.closed = true;
2313
- const children = Array.from(this.children);
2314
- const subScopes = Array.from(this.subScopes);
2315
- for (const child of children) {
2316
- child.interrupt();
2317
- }
2318
- const closeSubs = subScopes.reduceRight(
2319
- (acc, s) => asyncFlatMap(acc, () => s.closeAsync(exit, opts)),
2320
- unit()
2321
- );
2322
- const runFinalizers = this.buildFinalizerEffect(exit);
2323
- const needsAwait = opts.awaitChildren && children.length > 0;
2324
- const awaitChildrenEff = needsAwait ? awaitAll(children) : unit();
2325
- const hasSubScopes = subScopes.length > 0;
2326
- const hasNoFinalizers = this.finalizers.length === 0;
2327
- if (!hasSubScopes && !needsAwait && hasNoFinalizers) {
2328
- this.emitCloseEvent(exit);
2329
- cb({ _tag: "Success", value: void 0 });
2330
- return;
2331
- }
2332
- const all = asyncFlatMap(closeSubs, () => asyncFlatMap(awaitChildrenEff, () => runFinalizers));
2333
- this.runtime.fork(all).join(() => {
2334
- this.emitCloseEvent(exit);
2335
- cb({ _tag: "Success", value: void 0 });
2336
- });
2337
- })
2338
- );
2339
- }
2340
- };
2341
- function withScopeAsync(runtime, f) {
2342
- return async((_env, cb) => {
2343
- const scope = new Scope(runtime);
2344
- let done = false;
2345
- const completeAfterClose = (exit) => {
2346
- runtime.fork(scope.closeAsync(exit)).join(() => {
2347
- if (done) return;
2348
- done = true;
2349
- cb(exit);
2350
- });
2351
- };
2352
- const fiber = runtime.fork(f(scope));
2353
- fiber.join(completeAfterClose);
2354
- return () => {
2355
- if (done) return;
2356
- fiber.interrupt();
2357
- runtime.fork(scope.closeAsync(Exit.failCause(Cause.interrupt())));
2358
- };
2359
- });
2360
- }
2361
- function withScope(runtime, f) {
2362
- return withScopeAsync(runtime, (scope) => {
2363
- const out = f(scope);
2364
- if (out && typeof out === "object" && "_tag" in out) return out;
2365
- return unit();
2366
- });
2367
- }
2368
-
2369
- // src/core/stream/structuredConcurrency.ts
2370
- function race(left, right, parentScope) {
2371
- return async((env, cb) => {
2372
- const scope = parentScope.subScope();
2373
- let done = false;
2374
- const onResult = (exit) => {
2375
- if (done) return;
2376
- done = true;
2377
- scope.close(exit);
2378
- cb(exit);
2379
- };
2380
- const fiberLeft = scope.fork(left);
2381
- const fiberRight = scope.fork(right);
2382
- fiberLeft.join(onResult);
2383
- fiberRight.join(onResult);
2384
- });
2385
- }
2386
- function zipPar(left, right, parentScope) {
2387
- return async((env, cb) => {
2388
- const scope = parentScope.subScope();
2389
- let leftExit = null;
2390
- let rightExit = null;
2391
- let done = false;
2392
- const checkDone = () => {
2393
- if (!leftExit || !rightExit || done) return;
2394
- done = true;
2395
- if (leftExit._tag === "Success" && rightExit._tag === "Success") {
2396
- scope.close({ _tag: "Success", value: void 0 });
2397
- cb({
2398
- _tag: "Success",
2399
- value: [leftExit.value, rightExit.value]
2400
- });
2401
- return;
2402
- }
2403
- let cause;
2404
- if (leftExit._tag === "Failure") {
2405
- cause = leftExit.cause;
2406
- } else if (rightExit._tag === "Failure") {
2407
- cause = rightExit.cause;
2408
- } else {
2409
- throw new Error("zipPar: unreachable state (no Failure exit)");
2410
- }
2411
- const errExit = {
2412
- _tag: "Failure",
2413
- cause
2414
- };
2415
- scope.close(errExit);
2416
- cb(errExit);
2417
- };
2418
- const f1 = scope.fork(left);
2419
- const f2 = scope.fork(right);
2420
- f1.join((exit) => {
2421
- leftExit = exit;
2422
- checkDone();
2423
- });
2424
- f2.join((exit) => {
2425
- rightExit = exit;
2426
- checkDone();
2427
- });
2428
- });
2429
- }
2430
- function collectAllPar(effects, parentScope) {
2431
- return async((env, cb) => {
2432
- const scope = parentScope.subScope();
2433
- const results = new Array(effects.length);
2434
- let completed = 0;
2435
- let done = false;
2436
- effects.forEach((eff, i) => {
2437
- const f = scope.fork(eff);
2438
- f.join((exit) => {
2439
- if (done) return;
2440
- if (exit._tag === "Failure") {
2441
- done = true;
2442
- const errExit = {
2443
- _tag: "Failure",
2444
- cause: exit.cause
2445
- };
2446
- scope.close(errExit);
2447
- cb(errExit);
2448
- return;
2449
- }
2450
- results[i] = exit.value;
2451
- completed++;
2452
- if (completed === effects.length) {
2453
- done = true;
2454
- const successExit = {
2455
- _tag: "Success",
2456
- value: results
2457
- };
2458
- scope.close({ _tag: "Success", value: void 0 });
2459
- cb(successExit);
2460
- }
2461
- });
2462
- });
2463
- });
2464
- }
2465
- function raceWith(left, right, parentScope, onLeft, onRight) {
2466
- return async((env, cb) => {
2467
- const scope = parentScope.subScope();
2468
- let done = false;
2469
- const fiberLeft = scope.fork(left);
2470
- const fiberRight = scope.fork(right);
2471
- const finish = (next) => {
2472
- scope.fork(next).join((exitNext) => {
2473
- scope.close(exitNext);
2474
- cb(exitNext);
2475
- });
2476
- };
2477
- fiberLeft.join((exitL) => {
2478
- if (done) return;
2479
- done = true;
2480
- finish(onLeft(exitL, fiberRight, scope));
2481
- });
2482
- fiberRight.join((exitR) => {
2483
- if (done) return;
2484
- done = true;
2485
- finish(onRight(exitR, fiberLeft, scope));
2486
- });
2487
- });
2488
- }
2489
-
2490
- export {
2491
- Async,
2492
- asyncFold,
2493
- asyncCatchAll,
2494
- asyncMapError,
2495
- unit,
2496
- asyncSucceed,
2497
- asyncFail,
2498
- asyncSync,
2499
- asyncTotal,
2500
- async,
2501
- asyncMap,
2502
- asyncFlatMap,
2503
- acquireRelease,
2504
- asyncInterruptible,
2505
- withAsyncPromise,
2506
- mapAsync,
2507
- mapTryAsync,
2508
- none,
2509
- some,
2510
- Cause,
2511
- Exit,
2512
- succeed,
2513
- fail,
2514
- sync,
2515
- map,
2516
- flatMap,
2517
- mapError,
2518
- catchAll,
2519
- orElseOptional,
2520
- end,
2521
- PushStatus,
2522
- RingBuffer,
2523
- resolveWasmModule,
2524
- makeBoundedRingBuffer,
2525
- Scheduler,
2526
- globalScheduler,
2527
- setBenchmarkBudget,
2528
- getBenchmarkBudget,
2529
- RuntimeFiber,
2530
- getCurrentFiber,
2531
- unsafeGetCurrentRuntime,
2532
- withCurrentFiber,
2533
- DefaultHostExecutor,
2534
- JsFiberEngine,
2535
- HostRegistry,
2536
- ProgramBuilder,
2537
- EngineFiberHandle,
2538
- ReferenceWasmBridge,
2539
- WasmPackFiberBridge,
2540
- WasmFiberRegistryBridge,
2541
- WasmFiberEngine,
2542
- runtimeCapabilities,
2543
- NoopHooks,
2544
- Runtime,
2545
- fork,
2546
- unsafeRunAsync,
2547
- toPromise,
2548
- fromPromiseAbortable,
2549
- unsafeRunFoldWithEnv,
2550
- Scope,
2551
- withScopeAsync,
2552
- withScope,
2553
- race,
2554
- zipPar,
2555
- collectAllPar,
2556
- raceWith
2557
- };