brass-runtime 1.18.0 → 1.18.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/dist/agent/cli/main.cjs +31 -31
  3. package/dist/agent/cli/main.js +3 -3
  4. package/dist/agent/cli/main.mjs +3 -3
  5. package/dist/agent/index.cjs +4 -4
  6. package/dist/agent/index.d.ts +1 -1
  7. package/dist/agent/index.js +3 -3
  8. package/dist/agent/index.mjs +3 -3
  9. package/dist/{chunk-PSEU65ND.js → chunk-2R3RVNS2.js} +6 -6
  10. package/dist/{chunk-ITZQ526U.mjs → chunk-3NKXUX4T.mjs} +2 -2
  11. package/dist/{chunk-JH4GI3DW.js → chunk-4PKBNG2H.js} +38 -18
  12. package/dist/{chunk-Z3PSSXP3.mjs → chunk-5RVHSBJ6.mjs} +292 -36
  13. package/dist/{chunk-QZ6QFJNM.mjs → chunk-5UBJT4RW.mjs} +4 -4
  14. package/dist/{chunk-7TXQJFZX.cjs → chunk-6STX4PS3.cjs} +13 -13
  15. package/dist/{chunk-VIFA4DPN.cjs → chunk-7FZUTJM3.cjs} +508 -252
  16. package/dist/{chunk-4YQHPIWJ.js → chunk-A6EG5WRL.js} +3 -3
  17. package/dist/{chunk-XSAHV5HQ.js → chunk-APQBU7TM.js} +264 -133
  18. package/dist/{chunk-RREBJX2S.mjs → chunk-AQQQFNYD.mjs} +38 -18
  19. package/dist/{chunk-AADFFVYS.js → chunk-B2VXVNIS.js} +1 -1
  20. package/dist/{chunk-R6WDSZA6.mjs → chunk-BLXBZ6RE.mjs} +1 -1
  21. package/dist/{chunk-ITG6I7ZS.js → chunk-C3CWI42G.js} +1 -1
  22. package/dist/{chunk-LXBU5E77.cjs → chunk-DV644N7P.cjs} +85 -85
  23. package/dist/{chunk-G5JTCFMI.mjs → chunk-EKLEDIVJ.mjs} +2 -2
  24. package/dist/{chunk-IBRHSH5H.js → chunk-EXBGIC66.js} +1 -1
  25. package/dist/{chunk-W6WR37HN.js → chunk-FC5N5QHJ.js} +2 -2
  26. package/dist/{chunk-6MLAZPBL.mjs → chunk-FNWOH2T2.js} +18 -6
  27. package/dist/{chunk-AJMKZXRB.cjs → chunk-FYWWU3Z7.cjs} +2 -2
  28. package/dist/{chunk-IFRBVMWJ.cjs → chunk-GOEO763K.cjs} +21 -21
  29. package/dist/{chunk-S4HHFUYP.js → chunk-GXOIUBKE.js} +2 -2
  30. package/dist/{chunk-BG5RNEA2.js → chunk-H4ZRUQZL.js} +4 -4
  31. package/dist/{chunk-OI4ESUMC.mjs → chunk-HW2CLRJ3.mjs} +6 -6
  32. package/dist/{chunk-3PHU7FWS.js → chunk-JWFOWPMB.js} +163 -155
  33. package/dist/{chunk-OT2TESZU.mjs → chunk-KAPZHDO4.mjs} +1 -1
  34. package/dist/{chunk-ELLF55ER.mjs → chunk-KDXNWGPB.mjs} +1 -1
  35. package/dist/{chunk-UUMKZJRJ.cjs → chunk-KPOL2YEO.cjs} +18 -6
  36. package/dist/{chunk-2SLT3X6G.cjs → chunk-MA74OYCI.cjs} +6 -6
  37. package/dist/{chunk-2QNREG6K.mjs → chunk-MUMBUXU6.mjs} +264 -133
  38. package/dist/{chunk-YTX2JYYP.cjs → chunk-NQW3YUFN.cjs} +18 -18
  39. package/dist/{chunk-3PFZGP23.cjs → chunk-OO7BGCC3.cjs} +54 -34
  40. package/dist/{chunk-QCOLAHU3.mjs → chunk-OX6MF7SZ.mjs} +163 -155
  41. package/dist/{chunk-KHACHFBQ.cjs → chunk-QBVS3UYN.cjs} +245 -237
  42. package/dist/{chunk-H5GYX7RZ.js → chunk-RZGB3DXR.js} +292 -36
  43. package/dist/{chunk-KRYP6CAE.mjs → chunk-URVS2OE2.mjs} +3 -3
  44. package/dist/{chunk-HCJ4S3YB.js → chunk-UZQ3BB6W.mjs} +18 -6
  45. package/dist/{chunk-N6QNSTWD.cjs → chunk-YQWZ7FZX.cjs} +5 -5
  46. package/dist/{chunk-5XADBMSU.cjs → chunk-Z2YIDHRI.cjs} +5 -5
  47. package/dist/{chunk-SSQJKDN3.cjs → chunk-ZDZNV6NA.cjs} +286 -155
  48. package/dist/core/index.cjs +14 -8
  49. package/dist/core/index.d.ts +6 -6
  50. package/dist/core/index.js +13 -7
  51. package/dist/core/index.mjs +13 -7
  52. package/dist/{defaultClient-DhpCQW9m.d.ts → defaultClient-Cid0JoUR.d.ts} +29 -4
  53. package/dist/{effect-CtUDl5M5.d.ts → effect-DnGUuhw6.d.ts} +22 -1
  54. package/dist/http/index.cjs +58 -54
  55. package/dist/http/index.d.ts +8 -8
  56. package/dist/http/index.js +11 -7
  57. package/dist/http/index.mjs +11 -7
  58. package/dist/http/testing.cjs +9 -9
  59. package/dist/http/testing.d.ts +4 -4
  60. package/dist/http/testing.js +5 -5
  61. package/dist/http/testing.mjs +5 -5
  62. package/dist/index.cjs +92 -86
  63. package/dist/index.d.ts +7 -7
  64. package/dist/index.js +14 -8
  65. package/dist/index.mjs +14 -8
  66. package/dist/{layer-BalPI6cN.d.ts → layer-D2LFcBVx.d.ts} +1 -1
  67. package/dist/observability/index.cjs +10 -10
  68. package/dist/observability/index.d.ts +7 -7
  69. package/dist/observability/index.js +9 -9
  70. package/dist/observability/index.mjs +9 -9
  71. package/dist/perf/cli.cjs +26 -26
  72. package/dist/perf/cli.js +11 -11
  73. package/dist/perf/cli.mjs +11 -11
  74. package/dist/perf/index.cjs +13 -13
  75. package/dist/perf/index.js +11 -11
  76. package/dist/perf/index.mjs +11 -11
  77. package/dist/schema/index.cjs +2 -2
  78. package/dist/schema/index.js +1 -1
  79. package/dist/schema/index.mjs +1 -1
  80. package/dist/{server-C1zVmqE6.d.ts → server-Bf1zNYZk.d.ts} +4 -4
  81. package/dist/{stream-Bb4FTejt.d.ts → stream-I7bkvF7a.d.ts} +1 -1
  82. package/dist/{tracer-DzfuE6um.d.ts → tracer-DF83nLn6.d.ts} +2 -2
  83. package/dist/{tracing-BABA5arE.d.ts → tracing-CWV4gT0u.d.ts} +1 -1
  84. package/package.json +3 -2
@@ -2,14 +2,14 @@ import {
2
2
  EventBus,
3
3
  InMemoryTracer,
4
4
  makeMetrics
5
- } from "./chunk-AADFFVYS.js";
5
+ } from "./chunk-B2VXVNIS.js";
6
6
  import {
7
7
  Runtime,
8
8
  ctxExtend,
9
9
  ctxToObject,
10
10
  emptyContext,
11
11
  getCurrentFiber
12
- } from "./chunk-XSAHV5HQ.js";
12
+ } from "./chunk-APQBU7TM.js";
13
13
  import {
14
14
  asyncFail,
15
15
  asyncFlatMap,
@@ -20,7 +20,7 @@ import {
20
20
  import {
21
21
  Schema,
22
22
  parseConfig
23
- } from "./chunk-HCJ4S3YB.js";
23
+ } from "./chunk-FNWOH2T2.js";
24
24
 
25
25
  // src/observability/health.ts
26
26
  function snapshotRuntimeHealth(options = {}) {
@@ -10,7 +10,7 @@ import {
10
10
  import {
11
11
  Schema,
12
12
  parseConfig
13
- } from "./chunk-HCJ4S3YB.js";
13
+ } from "./chunk-FNWOH2T2.js";
14
14
 
15
15
  // src/core/runtime/ringBuffer.ts
16
16
  var PushStatus = /* @__PURE__ */ ((PushStatus3) => {
@@ -2950,31 +2950,43 @@ var Runtime = class _Runtime {
2950
2950
  const fiber = this.fork(effect);
2951
2951
  fiber.join(cb);
2952
2952
  }
2953
+ static exitToError(exit) {
2954
+ if (exit._tag === "Success") return void 0;
2955
+ const failure = Cause.firstFailure(exit.cause);
2956
+ if (failure._tag === "Some") return failure.value;
2957
+ const defect = Cause.firstDefect(exit.cause);
2958
+ if (defect._tag === "Some") {
2959
+ return defect.value instanceof Error ? defect.value : new Error(String(defect.value));
2960
+ }
2961
+ if (Cause.containsInterrupt(exit.cause)) return new Error("Interrupted");
2962
+ return Cause.toError(exit.cause);
2963
+ }
2953
2964
  toPromise(effect) {
2965
+ let syncExit;
2966
+ let promiseResolve;
2967
+ let promiseReject;
2968
+ const complete = (exit) => {
2969
+ if (promiseResolve) {
2970
+ if (exit._tag === "Success") promiseResolve(exit.value);
2971
+ else promiseReject(_Runtime.exitToError(exit));
2972
+ } else {
2973
+ syncExit = exit;
2974
+ }
2975
+ };
2976
+ if (this.tryRunNativeTopLevel(effect, complete)) {
2977
+ if (syncExit) {
2978
+ return syncExit._tag === "Success" ? Promise.resolve(syncExit.value) : Promise.reject(_Runtime.exitToError(syncExit));
2979
+ }
2980
+ return new Promise((resolve, reject) => {
2981
+ promiseResolve = resolve;
2982
+ promiseReject = reject;
2983
+ });
2984
+ }
2954
2985
  return new Promise((resolve, reject) => {
2955
- const complete = (exit) => {
2956
- if (exit._tag === "Success") {
2957
- resolve(exit.value);
2958
- return;
2959
- }
2960
- const failure = Cause.firstFailure(exit.cause);
2961
- if (failure._tag === "Some") reject(failure.value);
2962
- else {
2963
- const defect = Cause.firstDefect(exit.cause);
2964
- if (defect._tag === "Some") {
2965
- reject(defect.value instanceof Error ? defect.value : new Error(String(defect.value)));
2966
- } else if (Cause.containsInterrupt(exit.cause)) {
2967
- reject(new Error("Interrupted"));
2968
- } else {
2969
- reject(Cause.toError(exit.cause));
2970
- }
2971
- }
2972
- };
2973
- if (this.tryRunNativeTopLevel(effect, complete)) return;
2986
+ promiseResolve = resolve;
2987
+ promiseReject = reject;
2974
2988
  const fiber = this.fork(effect);
2975
- fiber.join((exit) => {
2976
- complete(exit);
2977
- });
2989
+ fiber.join(complete);
2978
2990
  });
2979
2991
  }
2980
2992
  tryRunNativeTopLevel(effect, cb) {
@@ -3017,32 +3029,43 @@ var NativeTopLevelRunner = class {
3017
3029
  constructor(runtime, effect, cb) {
3018
3030
  this.runtime = runtime;
3019
3031
  this.current = effect;
3020
- this.joiners.push(cb);
3021
- this.frame = {
3022
- id: 0,
3023
- runtime,
3024
- name: "native-fast-path",
3025
- fiberContext: { trace: null },
3026
- lane: runtime.lane,
3027
- status: () => this.result ? "Done" : "Running",
3028
- join: (joiner) => {
3029
- if (this.result) joiner(this.result);
3030
- else this.joiners.push(joiner);
3031
- },
3032
- interrupt: () => void 0,
3033
- addFinalizer: (finalizer) => {
3034
- this.finalizers.push(finalizer);
3035
- }
3036
- };
3032
+ this.firstJoiner = cb;
3037
3033
  }
3038
3034
  runtime;
3039
3035
  current;
3040
- stack = [];
3041
- joiners = [];
3042
- finalizers = [];
3036
+ // Lazy-allocated — most requests don't need these
3037
+ stack;
3038
+ joiners;
3039
+ finalizers;
3043
3040
  result;
3044
3041
  yielded = false;
3045
- frame;
3042
+ firstJoiner;
3043
+ // Frame is now the runner itself — avoids allocating a separate frame object
3044
+ // with 4 closures per request. We implement the Fiber-like interface inline.
3045
+ id = 0;
3046
+ name = "native-fast-path";
3047
+ fiberContext = { trace: null };
3048
+ get lane() {
3049
+ return this.runtime.lane;
3050
+ }
3051
+ // Fiber-like interface methods (used by frame consumers)
3052
+ status() {
3053
+ return this.result ? "Done" : "Running";
3054
+ }
3055
+ join(joiner) {
3056
+ if (this.result) {
3057
+ joiner(this.result);
3058
+ return;
3059
+ }
3060
+ if (!this.joiners) this.joiners = [];
3061
+ this.joiners.push(joiner);
3062
+ }
3063
+ interrupt() {
3064
+ }
3065
+ addFinalizer(finalizer) {
3066
+ if (!this.finalizers) this.finalizers = [];
3067
+ this.finalizers.push(finalizer);
3068
+ }
3046
3069
  start() {
3047
3070
  this.runLoop();
3048
3071
  }
@@ -3067,10 +3090,12 @@ var NativeTopLevelRunner = class {
3067
3090
  }
3068
3091
  break;
3069
3092
  case "FlatMap":
3093
+ if (!this.stack) this.stack = [];
3070
3094
  this.stack.push({ _tag: "SuccessCont", k: current.andThen });
3071
3095
  this.current = current.first;
3072
3096
  break;
3073
3097
  case "Fold":
3098
+ if (!this.stack) this.stack = [];
3074
3099
  this.stack.push({
3075
3100
  _tag: "FoldCont",
3076
3101
  onFailure: current.onFailure,
@@ -3085,10 +3110,12 @@ var NativeTopLevelRunner = class {
3085
3110
  this.onSuccess(this.runtime.fork(current.effect, current.scopeId));
3086
3111
  break;
3087
3112
  case "Interruptibility":
3113
+ if (!this.stack) this.stack = [];
3088
3114
  this.stack.push({ _tag: "InterruptibilityCont" });
3089
3115
  this.current = current.effect;
3090
3116
  break;
3091
3117
  case "InterruptibilityMask":
3118
+ if (!this.stack) this.stack = [];
3092
3119
  this.stack.push({ _tag: "InterruptibilityCont" });
3093
3120
  try {
3094
3121
  this.current = current.body((effect) => ({
@@ -3101,6 +3128,7 @@ var NativeTopLevelRunner = class {
3101
3128
  }
3102
3129
  break;
3103
3130
  case "InterruptibilityRestore":
3131
+ if (!this.stack) this.stack = [];
3104
3132
  this.stack.push({ _tag: "InterruptibilityCont" });
3105
3133
  this.current = current.effect;
3106
3134
  break;
@@ -3109,6 +3137,7 @@ var NativeTopLevelRunner = class {
3109
3137
  const hadValue = refs.has(current.refId);
3110
3138
  const previousValue = refs.get(current.refId);
3111
3139
  refs.set(current.refId, current.value);
3140
+ if (!this.stack) this.stack = [];
3112
3141
  this.stack.push({
3113
3142
  _tag: "FiberRefCont",
3114
3143
  refId: current.refId,
@@ -3167,7 +3196,7 @@ var NativeTopLevelRunner = class {
3167
3196
  onSuccess(value) {
3168
3197
  let currentValue = value;
3169
3198
  while (true) {
3170
- const frame = this.stack.pop();
3199
+ const frame = this.stack ? this.stack.pop() : void 0;
3171
3200
  if (!frame) {
3172
3201
  this.notify(Exit.succeed(currentValue));
3173
3202
  return;
@@ -3195,7 +3224,7 @@ var NativeTopLevelRunner = class {
3195
3224
  }
3196
3225
  onCause(cause) {
3197
3226
  let currentCause = cause;
3198
- while (this.stack.length > 0) {
3227
+ while (this.stack && this.stack.length > 0) {
3199
3228
  const frame = this.stack.pop();
3200
3229
  if (frame._tag === "InterruptibilityCont") continue;
3201
3230
  if (frame._tag === "FiberRefCont") {
@@ -3220,13 +3249,17 @@ var NativeTopLevelRunner = class {
3220
3249
  notify(exit) {
3221
3250
  if (this.result) return;
3222
3251
  this.result = exit;
3223
- this.runFinalizers(exit);
3224
- for (const joiner of this.joiners) joiner(exit);
3225
- this.joiners.length = 0;
3252
+ if (this.finalizers) this.runFinalizers(exit);
3253
+ this.firstJoiner(exit);
3254
+ if (this.joiners) {
3255
+ for (const joiner of this.joiners) joiner(exit);
3256
+ this.joiners.length = 0;
3257
+ }
3226
3258
  }
3227
3259
  runFinalizers(exit) {
3228
- while (this.finalizers.length > 0) {
3229
- const finalizer = this.finalizers.pop();
3260
+ const finalizers = this.finalizers;
3261
+ while (finalizers.length > 0) {
3262
+ const finalizer = finalizers.pop();
3230
3263
  try {
3231
3264
  const result = finalizer(exit);
3232
3265
  if (result && typeof result === "object" && "_tag" in result) {
@@ -3237,8 +3270,8 @@ var NativeTopLevelRunner = class {
3237
3270
  }
3238
3271
  }
3239
3272
  fiberRefs() {
3240
- this.frame.fiberContext.fiberRefs ??= /* @__PURE__ */ new Map();
3241
- return this.frame.fiberContext.fiberRefs;
3273
+ this.fiberContext.fiberRefs ??= /* @__PURE__ */ new Map();
3274
+ return this.fiberContext.fiberRefs;
3242
3275
  }
3243
3276
  restoreFiberRef(frame) {
3244
3277
  const refs = this.fiberRefs();
@@ -3246,7 +3279,7 @@ var NativeTopLevelRunner = class {
3246
3279
  else refs.delete(frame.refId);
3247
3280
  }
3248
3281
  withFrame(body) {
3249
- return withCurrentFiber(this.frame, body);
3282
+ return withCurrentFiber(this, body);
3250
3283
  }
3251
3284
  };
3252
3285
  function fork(effect, env) {
@@ -3274,6 +3307,12 @@ var abortablePromiseTotals = {
3274
3307
  lateSettlements: 0
3275
3308
  };
3276
3309
  var abortablePromiseLabels = /* @__PURE__ */ new Map();
3310
+ var perLabelTrackingEnabled = false;
3311
+ function setAbortablePromisePerLabelTracking(enabled) {
3312
+ const previous = perLabelTrackingEnabled;
3313
+ perLabelTrackingEnabled = enabled;
3314
+ return previous;
3315
+ }
3277
3316
  var getAbortablePromiseLabelStats = (label) => {
3278
3317
  const existing = abortablePromiseLabels.get(label);
3279
3318
  if (existing) return existing;
@@ -3291,44 +3330,60 @@ var getAbortablePromiseLabelStats = (label) => {
3291
3330
  return created;
3292
3331
  };
3293
3332
  var recordAbortablePromiseStart = (label) => {
3294
- const byLabel = getAbortablePromiseLabelStats(label);
3295
3333
  abortablePromiseTotals.active++;
3296
3334
  abortablePromiseTotals.started++;
3297
- byLabel.active++;
3298
- byLabel.started++;
3335
+ if (perLabelTrackingEnabled) {
3336
+ const byLabel = getAbortablePromiseLabelStats(label);
3337
+ byLabel.active++;
3338
+ byLabel.started++;
3339
+ }
3299
3340
  };
3300
3341
  var recordAbortablePromiseFinish = (label, outcome) => {
3301
- const byLabel = getAbortablePromiseLabelStats(label);
3302
3342
  if (abortablePromiseTotals.active > 0) abortablePromiseTotals.active--;
3303
- if (byLabel.active > 0) byLabel.active--;
3304
3343
  switch (outcome) {
3305
3344
  case "success":
3306
3345
  abortablePromiseTotals.succeeded++;
3307
- byLabel.succeeded++;
3308
- return;
3346
+ break;
3309
3347
  case "failure":
3310
3348
  abortablePromiseTotals.failed++;
3311
- byLabel.failed++;
3312
- return;
3349
+ break;
3313
3350
  case "interrupt":
3314
3351
  abortablePromiseTotals.interrupted++;
3315
- byLabel.interrupted++;
3316
- return;
3352
+ break;
3317
3353
  case "timeout":
3318
3354
  abortablePromiseTotals.timedOut++;
3319
- byLabel.timedOut++;
3320
- return;
3355
+ break;
3356
+ }
3357
+ if (perLabelTrackingEnabled) {
3358
+ const byLabel = getAbortablePromiseLabelStats(label);
3359
+ if (byLabel.active > 0) byLabel.active--;
3360
+ switch (outcome) {
3361
+ case "success":
3362
+ byLabel.succeeded++;
3363
+ return;
3364
+ case "failure":
3365
+ byLabel.failed++;
3366
+ return;
3367
+ case "interrupt":
3368
+ byLabel.interrupted++;
3369
+ return;
3370
+ case "timeout":
3371
+ byLabel.timedOut++;
3372
+ return;
3373
+ }
3321
3374
  }
3322
3375
  };
3323
3376
  var recordAbortablePromiseLateSettlement = (label) => {
3324
- const byLabel = getAbortablePromiseLabelStats(label);
3325
3377
  abortablePromiseTotals.lateSettlements++;
3326
- byLabel.lateSettlements++;
3378
+ if (perLabelTrackingEnabled) {
3379
+ const byLabel = getAbortablePromiseLabelStats(label);
3380
+ byLabel.lateSettlements++;
3381
+ }
3327
3382
  };
3328
3383
  function abortablePromiseStats() {
3329
3384
  return {
3330
3385
  ...abortablePromiseTotals,
3331
- byLabel: Array.from(abortablePromiseLabels.values()).map((x) => ({ ...x })).sort((a, b) => b.active - a.active || b.started - a.started || a.label.localeCompare(b.label))
3386
+ byLabel: perLabelTrackingEnabled ? Array.from(abortablePromiseLabels.values()).map((x) => ({ ...x })).sort((a, b) => b.active - a.active || b.started - a.started || a.label.localeCompare(b.label)) : []
3332
3387
  };
3333
3388
  }
3334
3389
  function resetAbortablePromiseStats() {
@@ -3350,76 +3405,149 @@ var makeTimeoutReason = (timeoutMs, label) => ({
3350
3405
  timeoutMs,
3351
3406
  message: `Abortable promise '${label}' timed out after ${timeoutMs}ms`
3352
3407
  });
3408
+ function registerWithTimeout(make, onReject, options, env, cb, timeoutMs) {
3409
+ const controller = new AbortController();
3410
+ const label = normalizeAbortablePromiseLabel(options.label);
3411
+ const startedAt = performance.now();
3412
+ let done = false;
3413
+ let cleanup;
3414
+ const hasHooks = options.onStart !== void 0 || options.onFinish !== void 0;
3415
+ const finish = hasHooks ? (outcome, exit, error) => {
3416
+ if (done) return;
3417
+ done = true;
3418
+ cleanup();
3419
+ recordAbortablePromiseFinish(label, outcome);
3420
+ options.onFinish?.({
3421
+ label,
3422
+ outcome,
3423
+ durationMs: Math.round(performance.now() - startedAt),
3424
+ error
3425
+ });
3426
+ cb(exit);
3427
+ } : (outcome, exit, _error) => {
3428
+ if (done) return;
3429
+ done = true;
3430
+ cleanup();
3431
+ recordAbortablePromiseFinish(label, outcome);
3432
+ cb(exit);
3433
+ };
3434
+ recordAbortablePromiseStart(label);
3435
+ if (hasHooks) options.onStart?.(label);
3436
+ const onTimeout = () => {
3437
+ const reason = options.timeoutReason?.() ?? makeTimeoutReason(timeoutMs, label);
3438
+ try {
3439
+ controller.abort(reason);
3440
+ } catch {
3441
+ controller.abort();
3442
+ }
3443
+ finish("timeout", Exit.failCause(Cause.fail(onReject(reason))), reason);
3444
+ };
3445
+ if (options.timerWheel) {
3446
+ const handle = options.timerWheel.schedule(timeoutMs, onTimeout);
3447
+ cleanup = () => {
3448
+ handle.cancel();
3449
+ };
3450
+ } else {
3451
+ let timeoutHandle = setTimeout(onTimeout, timeoutMs);
3452
+ cleanup = () => {
3453
+ if (timeoutHandle !== void 0) {
3454
+ clearTimeout(timeoutHandle);
3455
+ timeoutHandle = void 0;
3456
+ }
3457
+ };
3458
+ }
3459
+ let promise;
3460
+ try {
3461
+ promise = make(controller.signal, env);
3462
+ } catch (err) {
3463
+ finish("failure", Exit.failCause(Cause.fail(onReject(err))), err);
3464
+ return () => void 0;
3465
+ }
3466
+ promise.then((value) => {
3467
+ if (done) {
3468
+ recordAbortablePromiseLateSettlement(label);
3469
+ return;
3470
+ }
3471
+ finish("success", Exit.succeed(value));
3472
+ }).catch((err) => {
3473
+ if (done) {
3474
+ recordAbortablePromiseLateSettlement(label);
3475
+ return;
3476
+ }
3477
+ finish("failure", Exit.failCause(Cause.fail(onReject(err))), err);
3478
+ });
3479
+ return () => {
3480
+ if (done) return;
3481
+ try {
3482
+ controller.abort();
3483
+ } catch {
3484
+ }
3485
+ finish("interrupt", Exit.failCause(Cause.interrupt()));
3486
+ };
3487
+ }
3488
+ function registerWithoutTimeout(make, onReject, options, env, cb) {
3489
+ const controller = new AbortController();
3490
+ const label = normalizeAbortablePromiseLabel(options.label);
3491
+ const startedAt = performance.now();
3492
+ let done = false;
3493
+ const hasHooks = options.onStart !== void 0 || options.onFinish !== void 0;
3494
+ const finish = hasHooks ? (outcome, exit, error) => {
3495
+ if (done) return;
3496
+ done = true;
3497
+ recordAbortablePromiseFinish(label, outcome);
3498
+ options.onFinish?.({
3499
+ label,
3500
+ outcome,
3501
+ durationMs: Math.round(performance.now() - startedAt),
3502
+ error
3503
+ });
3504
+ cb(exit);
3505
+ } : (outcome, exit, _error) => {
3506
+ if (done) return;
3507
+ done = true;
3508
+ recordAbortablePromiseFinish(label, outcome);
3509
+ cb(exit);
3510
+ };
3511
+ recordAbortablePromiseStart(label);
3512
+ if (hasHooks) options.onStart?.(label);
3513
+ let promise;
3514
+ try {
3515
+ promise = make(controller.signal, env);
3516
+ } catch (err) {
3517
+ finish("failure", Exit.failCause(Cause.fail(onReject(err))), err);
3518
+ return () => void 0;
3519
+ }
3520
+ promise.then((value) => {
3521
+ if (done) {
3522
+ recordAbortablePromiseLateSettlement(label);
3523
+ return;
3524
+ }
3525
+ finish("success", Exit.succeed(value));
3526
+ }).catch((err) => {
3527
+ if (done) {
3528
+ recordAbortablePromiseLateSettlement(label);
3529
+ return;
3530
+ }
3531
+ finish("failure", Exit.failCause(Cause.fail(onReject(err))), err);
3532
+ });
3533
+ return () => {
3534
+ if (done) return;
3535
+ try {
3536
+ controller.abort();
3537
+ } catch {
3538
+ }
3539
+ finish("interrupt", Exit.failCause(Cause.interrupt()));
3540
+ };
3541
+ }
3353
3542
  function fromPromiseAbortable(make, onReject, options = {}) {
3354
3543
  return {
3355
3544
  _tag: "Async",
3356
3545
  register: (env, cb) => {
3357
- const controller = new AbortController();
3358
- const label = normalizeAbortablePromiseLabel(options.label);
3359
3546
  const timeoutMs = options.timeoutMs !== void 0 && Number.isFinite(options.timeoutMs) ? Math.max(0, Math.floor(options.timeoutMs)) : void 0;
3360
- const startedAt = performance.now();
3361
- let done = false;
3362
- let timeoutHandle;
3363
- const cleanup = () => {
3364
- if (timeoutHandle !== void 0) {
3365
- clearTimeout(timeoutHandle);
3366
- timeoutHandle = void 0;
3367
- }
3368
- };
3369
- const finish = (outcome, exit, error) => {
3370
- if (done) return;
3371
- done = true;
3372
- cleanup();
3373
- recordAbortablePromiseFinish(label, outcome);
3374
- options.onFinish?.({
3375
- label,
3376
- outcome,
3377
- durationMs: Math.round(performance.now() - startedAt),
3378
- error
3379
- });
3380
- cb(exit);
3381
- };
3382
- recordAbortablePromiseStart(label);
3383
- options.onStart?.(label);
3384
3547
  if (timeoutMs !== void 0 && timeoutMs > 0) {
3385
- timeoutHandle = setTimeout(() => {
3386
- const reason = options.timeoutReason?.() ?? makeTimeoutReason(timeoutMs, label);
3387
- try {
3388
- controller.abort(reason);
3389
- } catch {
3390
- controller.abort();
3391
- }
3392
- finish("timeout", Exit.failCause(Cause.fail(onReject(reason))), reason);
3393
- }, timeoutMs);
3548
+ return registerWithTimeout(make, onReject, options, env, cb, timeoutMs);
3394
3549
  }
3395
- let promise;
3396
- try {
3397
- promise = make(controller.signal, env);
3398
- } catch (err) {
3399
- finish("failure", Exit.failCause(Cause.fail(onReject(err))), err);
3400
- return () => void 0;
3401
- }
3402
- promise.then((value) => {
3403
- if (done) {
3404
- recordAbortablePromiseLateSettlement(label);
3405
- return;
3406
- }
3407
- finish("success", Exit.succeed(value));
3408
- }).catch((err) => {
3409
- if (done) {
3410
- recordAbortablePromiseLateSettlement(label);
3411
- return;
3412
- }
3413
- finish("failure", Exit.failCause(Cause.fail(onReject(err))), err);
3414
- });
3415
- return () => {
3416
- if (done) return;
3417
- try {
3418
- controller.abort();
3419
- } catch {
3420
- }
3421
- finish("interrupt", Exit.failCause(Cause.interrupt()));
3422
- };
3550
+ return registerWithoutTimeout(make, onReject, options, env, cb);
3423
3551
  }
3424
3552
  };
3425
3553
  }
@@ -4256,6 +4384,9 @@ export {
4256
4384
  toPromiseByCaller,
4257
4385
  unsafeRunAsync,
4258
4386
  toPromise,
4387
+ setAbortablePromisePerLabelTracking,
4388
+ recordAbortablePromiseStart,
4389
+ recordAbortablePromiseFinish,
4259
4390
  abortablePromiseStats,
4260
4391
  resetAbortablePromiseStats,
4261
4392
  fromPromiseAbortable,
@@ -6,7 +6,7 @@ import {
6
6
  getCurrentFiber,
7
7
  unsafeGetCurrentRuntime,
8
8
  unsafeRunFoldWithEnv
9
- } from "./chunk-2QNREG6K.mjs";
9
+ } from "./chunk-MUMBUXU6.mjs";
10
10
  import {
11
11
  Cause,
12
12
  Exit,
@@ -412,31 +412,49 @@ function drainStreamSyncFull(stream) {
412
412
  }
413
413
  }
414
414
  }
415
+ var ABORTED_ERROR = (() => {
416
+ if (typeof DOMException === "function") {
417
+ try {
418
+ return new DOMException("aborted", "AbortError");
419
+ } catch {
420
+ }
421
+ }
422
+ const e = new Error("aborted");
423
+ e.name = "AbortError";
424
+ return e;
425
+ })();
415
426
  function readerStream(reader, normalizeError, signal) {
427
+ const noopSignal = globalThis.__brassNoopSignal;
428
+ const needsSignalListener = signal !== void 0 && signal !== noopSignal;
416
429
  const pull = asyncEffect((_, cb) => {
417
430
  let done = false;
418
- const cleanup = () => signal?.removeEventListener("abort", abort);
431
+ let abortFn;
419
432
  const finish = (exit) => {
420
433
  if (done) return;
421
434
  done = true;
422
- cleanup();
435
+ if (needsSignalListener && abortFn) signal.removeEventListener("abort", abortFn);
423
436
  cb(exit);
424
437
  };
425
- const abort = () => {
426
- try {
427
- reader.cancel();
428
- } catch {
438
+ if (needsSignalListener) {
439
+ if (signal.aborted) {
440
+ try {
441
+ reader.cancel();
442
+ } catch {
443
+ }
444
+ finish({ _tag: "Failure", cause: { _tag: "Fail", error: some(normalizeError(ABORTED_ERROR)) } });
445
+ return;
429
446
  }
430
- const error = typeof DOMException === "function" ? new DOMException("aborted", "AbortError") : new Error("aborted");
431
- finish({ _tag: "Failure", cause: { _tag: "Fail", error: some(normalizeError(error)) } });
432
- };
433
- if (signal?.aborted) {
434
- abort();
435
- return;
447
+ abortFn = () => {
448
+ try {
449
+ reader.cancel();
450
+ } catch {
451
+ }
452
+ finish({ _tag: "Failure", cause: { _tag: "Fail", error: some(normalizeError(ABORTED_ERROR)) } });
453
+ };
454
+ signal.addEventListener("abort", abortFn, { once: true });
436
455
  }
437
- signal?.addEventListener("abort", abort, { once: true });
438
- reader.read().then(({ done: done2, value }) => {
439
- if (done2) {
456
+ reader.read().then(({ done: readDone, value }) => {
457
+ if (readDone) {
440
458
  finish({ _tag: "Failure", cause: { _tag: "Fail", error: none } });
441
459
  return;
442
460
  }
@@ -444,11 +462,13 @@ function readerStream(reader, normalizeError, signal) {
444
462
  _tag: "Success",
445
463
  value: [value, fromPull(pull)]
446
464
  });
447
- }).catch((e) => {
465
+ }, (e) => {
448
466
  finish({ _tag: "Failure", cause: { _tag: "Fail", error: some(normalizeError(e)) } });
449
467
  });
450
468
  return () => {
451
- cleanup();
469
+ if (done) return;
470
+ done = true;
471
+ if (needsSignalListener && abortFn) signal.removeEventListener("abort", abortFn);
452
472
  try {
453
473
  reader.cancel();
454
474
  } catch {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  makeBoundedRingBuffer
3
- } from "./chunk-XSAHV5HQ.js";
3
+ } from "./chunk-APQBU7TM.js";
4
4
  import {
5
5
  Cause
6
6
  } from "./chunk-UB4B6OFY.js";
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  fromPromiseAbortable,
6
6
  withScopeAsync
7
- } from "./chunk-2QNREG6K.mjs";
7
+ } from "./chunk-MUMBUXU6.mjs";
8
8
  import {
9
9
  Cause,
10
10
  Exit,
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  fromPromiseAbortable,
6
6
  withScopeAsync
7
- } from "./chunk-XSAHV5HQ.js";
7
+ } from "./chunk-APQBU7TM.js";
8
8
  import {
9
9
  Cause,
10
10
  Exit,