uneventful 0.0.9 → 0.0.11

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.
@@ -1,4 +1,4 @@
1
- import { b as batch, d as defer, i as isFunction, G as GeneratorBase, c as apply } from './utils-P0JEpWXG.mjs';
1
+ import { e as batch, d as defer, i as isFunction, G as GeneratorBase, c as apply } from './utils-cyEhnyp7.mjs';
2
2
 
3
3
  function resolve(request, val) {
4
4
  request("next", val);
@@ -44,12 +44,13 @@ function markHandled(res) {
44
44
  return res.err;
45
45
  }
46
46
  function getResult(res) {
47
- if (isValue(res))
48
- return res.val;
49
- res.op;
50
- fulfillPromise(noop, (e) => {
51
- throw e;
52
- }, res);
47
+ if (!isValue(res)) {
48
+ res.op;
49
+ fulfillPromise(noop, (e) => {
50
+ throw e;
51
+ }, res);
52
+ }
53
+ return res.val;
53
54
  }
54
55
  function fulfillPromise(resolve2, reject2, res) {
55
56
  if (isError(res))
@@ -66,31 +67,25 @@ function propagateResult(job, res) {
66
67
  class CancelError extends Error {
67
68
  }
68
69
 
69
- var current = makeCtx();
70
- function swapCtx(future) {
71
- const now = current;
72
- current = future;
73
- return now;
74
- }
75
- var freelist = [];
76
- function makeCtx(job, cell) {
77
- if (freelist && freelist.length) {
78
- const s = freelist.pop();
79
- s.job = job;
80
- s.cell = cell;
81
- return s;
82
- }
83
- return { job, cell };
84
- }
85
- function freeCtx(s) {
86
- s.job = s.cell = null;
87
- freelist.push(s);
70
+ var currentJob, currentCell;
71
+ const cells = [], jobs = [];
72
+ function pushCtx(job, cell) {
73
+ jobs.push(currentJob);
74
+ cells.push(currentCell);
75
+ currentJob = job;
76
+ currentCell = cell;
77
+ }
78
+ function popCtx() {
79
+ currentJob = jobs.pop();
80
+ currentCell = cells.pop();
81
+ }
82
+ function cellJob() {
83
+ return currentJob ||= currentCell?.getJob();
88
84
  }
89
85
 
90
86
  const catchers = /* @__PURE__ */ new WeakMap(), defaultCatch = (e) => {
91
87
  Promise.reject(e);
92
88
  };
93
- const nullCtx = makeCtx();
94
89
  const owners = /* @__PURE__ */ new WeakMap();
95
90
  const pulls = /* @__PURE__ */ batch((pulls2) => {
96
91
  for (const conn of pulls2) {
@@ -127,8 +122,7 @@ function qlen(c) {
127
122
  return c ? c.v : 0;
128
123
  }
129
124
  function pop(c) {
130
- if (qlen(c))
131
- return unlink(c, c.p);
125
+ return qlen(c) ? unlink(c, c.p) : void 0;
132
126
  }
133
127
  class Node {
134
128
  constructor() {
@@ -185,22 +179,23 @@ function unlinker(chain2, node) {
185
179
  }
186
180
 
187
181
  function getJob() {
188
- const job = current.job || current.cell?.getJob();
182
+ const job = currentJob || cellJob();
189
183
  if (job)
190
184
  return job;
191
185
  throw new Error("No job is currently active");
192
186
  }
193
187
  function recalcJob(job) {
194
188
  return (cb) => {
195
- current.job.must(job.release(cb));
189
+ currentJob.must(job.release(cb));
196
190
  };
197
191
  }
198
192
  function runChain(res, cbs) {
199
- while (qlen(cbs))
193
+ let cb;
194
+ while (cb = pop(cbs))
200
195
  try {
201
- pop(cbs)(res);
196
+ cb(res);
202
197
  } catch (e) {
203
- detached.asyncThrow(e);
198
+ _detached.asyncThrow(e);
204
199
  }
205
200
  cbs && recycle(cbs);
206
201
  return void 0;
@@ -212,14 +207,15 @@ class _Job {
212
207
  const res = this._done ||= CancelResult, cbs = this._cbs;
213
208
  if (!cbs && !isUnhandled(res))
214
209
  return;
215
- const ct = inProcess.size, old = swapCtx(nullCtx);
210
+ const ct = inProcess.size;
211
+ pushCtx();
216
212
  if (!ct)
217
213
  inProcess.add(null);
218
214
  if (cbs && cbs.u)
219
215
  cbs.u = runChain(res, cbs.u);
220
216
  inProcess.add(this);
221
217
  if (ct) {
222
- swapCtx(old);
218
+ popCtx();
223
219
  return;
224
220
  }
225
221
  inProcess.delete(null);
@@ -230,7 +226,7 @@ class _Job {
230
226
  if (isUnhandled(item._done))
231
227
  item.throw(markHandled(item._done));
232
228
  }
233
- swapCtx(old);
229
+ popCtx();
234
230
  };
235
231
  this._done = void 0;
236
232
  // Chain whose .u stores a second chain for `release()` callbacks
@@ -268,7 +264,7 @@ class _Job {
268
264
  });
269
265
  }
270
266
  result() {
271
- return this._done || current.cell?.recalcWhen(this, recalcJob) || void 0;
267
+ return this._done || currentCell?.recalcWhen(this, recalcJob) || void 0;
272
268
  }
273
269
  get [Symbol.toStringTag]() {
274
270
  return "Job";
@@ -289,14 +285,14 @@ class _Job {
289
285
  _end(res) {
290
286
  if (this._done)
291
287
  throw new Error("Job already ended");
292
- if (this !== detached)
288
+ if (this !== _detached)
293
289
  this._done = res;
294
290
  this.end();
295
291
  return this;
296
292
  }
297
293
  throw(err) {
298
294
  if (this._done) {
299
- (owners.get(this) || detached).asyncThrow(err);
295
+ (owners.get(this) || _detached).asyncThrow(err);
300
296
  return this;
301
297
  }
302
298
  return this._end(ErrorResult(err));
@@ -380,21 +376,21 @@ class _Job {
380
376
  return this.start((job) => void src(sink, job, inlet));
381
377
  }
382
378
  run(fn, ...args) {
383
- const old = swapCtx(makeCtx(this));
379
+ pushCtx(this);
384
380
  try {
385
381
  return fn(...args);
386
382
  } finally {
387
- freeCtx(swapCtx(old));
383
+ popCtx();
388
384
  }
389
385
  }
390
386
  bind(fn) {
391
387
  const job = this;
392
388
  return function() {
393
- const old = swapCtx(makeCtx(job));
389
+ pushCtx(job);
394
390
  try {
395
391
  return apply(fn, this, arguments);
396
392
  } finally {
397
- freeCtx(swapCtx(old));
393
+ popCtx();
398
394
  }
399
395
  };
400
396
  }
@@ -404,7 +400,7 @@ class _Job {
404
400
  return this;
405
401
  }
406
402
  release(cleanup) {
407
- if (this === detached)
403
+ if (this === _detached)
408
404
  return noop;
409
405
  let cbs = this._chain();
410
406
  if (!this._done || cbs.u)
@@ -415,7 +411,7 @@ class _Job {
415
411
  try {
416
412
  (catchers.get(this) || this.throw).call(this, err);
417
413
  } catch (e) {
418
- if (this === detached)
414
+ if (this === _detached)
419
415
  catchers.set(this, defaultCatch);
420
416
  else
421
417
  catchers.delete(this);
@@ -433,7 +429,7 @@ class _Job {
433
429
  return this;
434
430
  }
435
431
  _chain() {
436
- if (this === detached)
432
+ if (this === _detached)
437
433
  this.end();
438
434
  if (this._done && isEmpty(this._cbs))
439
435
  defer(this.end);
@@ -454,14 +450,23 @@ function nativePromise(job) {
454
450
  return promises.get(job);
455
451
  }
456
452
  const makeJob = _Job.create;
457
- const detached = makeJob();
458
- detached.end = () => {
453
+ const _detached = makeJob();
454
+ const detached = _detached;
455
+ _detached.end = () => {
459
456
  throw new Error("Can't do that with the detached job");
460
457
  };
461
- detached.asyncCatch(defaultCatch);
458
+ _detached.asyncCatch(defaultCatch);
459
+ let root;
460
+ newRoot();
461
+ function newRoot() {
462
+ root?.end();
463
+ const job = root = makeJob().asyncCatch((e) => _detached.asyncThrow(e));
464
+ job.release(() => root === job && (root = null));
465
+ return root;
466
+ }
462
467
  function runGen(g, job) {
463
- let it = g[Symbol.iterator](), running = true, ctx = makeCtx(job), ct = 0;
464
- let done = ctx.job.release(() => {
468
+ let it = g[Symbol.iterator](), running = true, j = job, ct = 0;
469
+ let done = job.release(() => {
465
470
  job = void 0;
466
471
  ++ct;
467
472
  step("return", void 0);
@@ -476,7 +481,7 @@ function runGen(g, job) {
476
481
  if (running) {
477
482
  return defer(step.bind(null, method, arg));
478
483
  }
479
- const old = swapCtx(ctx);
484
+ pushCtx(j);
480
485
  try {
481
486
  running = true;
482
487
  try {
@@ -510,107 +515,18 @@ function runGen(g, job) {
510
515
  }
511
516
  } catch (e) {
512
517
  it = job = void 0;
513
- ctx.job.throw(e);
518
+ j.throw(e);
514
519
  }
515
520
  it = void 0;
516
521
  done?.();
517
522
  done = void 0;
518
523
  } finally {
519
- swapCtx(old);
524
+ popCtx();
520
525
  running = false;
521
526
  }
522
527
  }
523
528
  }
524
529
 
525
- function backpressure(inlet = defaultInlet) {
526
- const job = getJob();
527
- return (cb) => {
528
- if (!job.result() && inlet.isOpen()) {
529
- if (cb)
530
- inlet.onReady(cb, job);
531
- return inlet.isReady();
532
- }
533
- return false;
534
- };
535
- }
536
- const IsStream = "uneventful/is-stream";
537
- function connect(src, sink, inlet) {
538
- return getJob().connect(src, sink, inlet);
539
- }
540
- function throttle(job = current.job) {
541
- return new _Throttle(job);
542
- }
543
- class _Throttle {
544
- /** @internal */
545
- constructor(_job) {
546
- this._job = _job;
547
- /** @internal */
548
- this._callbacks = void 0;
549
- this._isReady = true;
550
- this._isPulling = false;
551
- }
552
- isOpen() {
553
- return !this._job?.result();
554
- }
555
- /** Is the connection ready to receive data? */
556
- isReady() {
557
- return this.isOpen() && this._isReady;
558
- }
559
- onReady(cb, job) {
560
- if (!this.isOpen())
561
- return this;
562
- const _callbacks = this._callbacks ||= /* @__PURE__ */ new Map();
563
- const unlink = job.release(() => _callbacks.delete(cb));
564
- if (this.isReady() && this && !_callbacks.size) {
565
- pulls.add(this);
566
- }
567
- _callbacks.set(cb, unlink);
568
- return this;
569
- }
570
- pause() {
571
- this._isReady = false;
572
- return this;
573
- }
574
- doPull() {
575
- if (this._isPulling)
576
- return;
577
- const { _callbacks } = this;
578
- if (!_callbacks?.size)
579
- return;
580
- this._isPulling = true;
581
- try {
582
- for (let [cb, unlink] of _callbacks) {
583
- if (!this.isReady())
584
- break;
585
- unlink();
586
- _callbacks.delete(cb);
587
- cb();
588
- }
589
- } finally {
590
- this._isPulling = false;
591
- }
592
- }
593
- resume() {
594
- if (this.isOpen()) {
595
- this._isReady = true;
596
- this.doPull();
597
- }
598
- }
599
- }
600
- const defaultInlet = throttle();
601
- function pipe() {
602
- var v = arguments[0];
603
- for (var i = 1; i < arguments.length; i++)
604
- v = arguments[i](v);
605
- return v;
606
- }
607
- function compose(...fns) {
608
- return (val) => pipe(val, ...fns);
609
- }
610
- function into(...args) {
611
- return (src) => src(...args);
612
- }
613
-
614
530
  function must(cleanup) {
615
531
  getJob().must(cleanup);
616
532
  }
@@ -618,7 +534,7 @@ function start(init, fn) {
618
534
  return getJob().start(init, fn);
619
535
  }
620
536
  function isJobActive() {
621
- return !!current.job;
537
+ return !!currentJob;
622
538
  }
623
539
  const timers = /* @__PURE__ */ new WeakMap();
624
540
  function timeout(ms = 0, job = getJob()) {
@@ -664,14 +580,14 @@ function restarting(task2) {
664
580
  inner.asyncCatch((e) => outer.asyncThrow(e));
665
581
  return function() {
666
582
  inner.restart().must(outer.release(end));
667
- const old = swapCtx(makeCtx(inner));
583
+ pushCtx(inner);
668
584
  try {
669
585
  return apply(task2, this, arguments);
670
586
  } catch (e) {
671
587
  inner.restart();
672
588
  throw e;
673
589
  } finally {
674
- freeCtx(swapCtx(old));
590
+ popCtx();
675
591
  }
676
592
  };
677
593
  }
@@ -683,23 +599,4 @@ function task(fn, _ctx, desc) {
683
599
  };
684
600
  }
685
601
 
686
- function callOrWait(source, method, handler, noArgs) {
687
- if (source && isFunction(source[method]))
688
- return source[method]();
689
- if (isFunction(source))
690
- return (source.length === 0 ? noArgs(source) : false) || start((job) => {
691
- connect(source, (v) => handler(job, v)).do((r) => {
692
- if (isValue(r))
693
- job.throw(new Error("Stream ended"));
694
- else if (isError(r))
695
- job.throw(markHandled(r));
696
- });
697
- });
698
- mustBeSourceOrSignal();
699
- }
700
- function mustBeSourceOrSignal() {
701
- throw new TypeError("not a source or signal");
702
- }
703
-
704
- export { nativePromise as A, makeJob as B, CancelResult as C, pipe as D, ErrorResult as E, compose as F, into as G, isJobActive as H, IsStream as I, timeout as J, abortSignal as K, task as L, swapCtx as M, nullCtx as N, makeCtx as O, freeCtx as P, ValueResult as V, rejecter as a, resolve as b, backpressure as c, detached as d, isUnhandled as e, markHandled as f, getJob as g, isError as h, isCancel as i, connect as j, fulfillPromise as k, callOrWait as l, must as m, noop as n, restarting as o, current as p, mustBeSourceOrSignal as q, resolver as r, start as s, throttle as t, isValue as u, reject as v, isHandled as w, getResult as x, propagateResult as y, CancelError as z };
705
- //# sourceMappingURL=call-or-wait-DpJBh_pS.mjs.map
602
+ export { timeout as A, abortSignal as B, CancelResult as C, task as D, ErrorResult as E, pushCtx as F, popCtx as G, currentJob as H, pulls as I, ValueResult as V, rejecter as a, resolve as b, root as c, isUnhandled as d, markHandled as e, isError as f, getJob as g, fulfillPromise as h, isCancel as i, restarting as j, currentCell as k, isValue as l, must as m, noop as n, reject as o, isHandled as p, getResult as q, resolver as r, start as s, propagateResult as t, CancelError as u, nativePromise as v, makeJob as w, detached as x, newRoot as y, isJobActive as z };
package/dist/mod.d.ts CHANGED
@@ -6,6 +6,7 @@ export { a as Each, E as EachResult, N as NextMethod, U as UntilMethod, e as eac
6
6
  * Invoke a no-argument function as a microtask, using queueMicrotask or Promise.resolve().then()
7
7
  *
8
8
  * @category Scheduling
9
+ * @function
9
10
  */
10
11
  declare let defer: (cb: () => any) => void;
11
12
 
@@ -37,21 +38,30 @@ declare function nativePromise<T>(job: Job<T>): Promise<T>;
37
38
  * Return a new {@link Job}. If *either* a parent parameter or stop function
38
39
  * are given, the new job is linked to the parent.
39
40
  *
41
+ * @remarks You should generally use `start()`, `parent.start()` or
42
+ * `root.start()` instead of this, unless you're creating a special kind of job
43
+ * that needs a custom stop function.
44
+ *
40
45
  * @param parent The parent job to which the new job should be attached.
41
- * Defaults to the currently-active job if none given (assuming a stop
42
- * parameter is provided).
46
+ * Defaults to the currently-active job if none given (assuming a stop parameter
47
+ * is provided).
43
48
  *
44
49
  * @param stop The function to call to destroy the nested job. Defaults to the
45
50
  * {@link Job.end} method of the new job if none is given (assuming a parent
46
51
  * parameter is provided).
47
52
  *
48
- * @returns A new job. The job is linked/nested if any arguments are given,
49
- * or a detached (parentless) job otherwise.
53
+ * @returns A new job. The job is a child job if any arguments are given, or
54
+ * a detached (parentless) job otherwise.
50
55
  *
51
56
  * @category Jobs
57
+ * @function
52
58
  */
53
59
  declare const makeJob: <T>(parent?: Job, stop?: CleanupFn) => Job<T>;
54
60
  /**
61
+ * @deprecated Use {@link root} instead. (Including uses of
62
+ * `.asyncCatch()` to set the default async error handling policy.)
63
+ *
64
+ * ---
55
65
  * A special {@link Job} with no parents, that can be used to create standalone
56
66
  * jobs. detached.start() returns a new detached job, detached.run() can be
57
67
  * used to run code that expects to create a child job, and detached.bind() can
@@ -80,6 +90,56 @@ declare const makeJob: <T>(parent?: Job, stop?: CleanupFn) => Job<T>;
80
90
  * @category Jobs
81
91
  */
82
92
  declare const detached: Job<unknown>;
93
+ /**
94
+ * The "main" job of the program or bundle, which all other jobs should be a
95
+ * child of. This provides a single point of configuration and cleanup, as one
96
+ * can e.g.:
97
+ *
98
+ * - Use {@link Job.asyncCatch `root.asyncCatch()`} to define the default async
99
+ * error handling policy
100
+ * - Use {@link Job.end `root.end()`} to clean up all resources for the entire
101
+ * program
102
+ * - Use {@link Job.start `root.start()`} to create top-level, standalone, or
103
+ * "daemon"/service tasks, or to create tasks whose lifetime is managed by an
104
+ * external framework.
105
+ *
106
+ * By default, there is only ever one root job, run once, in a given process or
107
+ * page. But for testing you can use {@link newRoot} to end the existing root
108
+ * and start a new one.
109
+ *
110
+ * @remarks
111
+ * Uneventful does not include any code to end the root job itself, as the
112
+ * decision of when and whether to do that varies heavily by context (e.g.
113
+ * server vs. browser, app vs. plugin, etc.), and often doesn't need to happen
114
+ * at all. (Because exiting the process or leaving the web page is often
115
+ * sufficient.)
116
+ *
117
+ * More commonly, you will only end the root job when running tests (to get a
118
+ * clean environment for the next test), or when your entire bundle is itself an
119
+ * unloadable plugin (e.g. in Obsidian).
120
+ *
121
+ * Note, too, that when the root job ends, root is reset to `null` so that any
122
+ * subsequent attempt to use the root job will throw an exception. (Unless of
123
+ * course a new root job has been created with {@link newRoot}.)
124
+ *
125
+ * @category Jobs
126
+ */
127
+ declare let root: Job<unknown>;
128
+ /**
129
+ * Create a new root job (usually for testing purposes). If there is an existing
130
+ * root job, it is ended first. The new root is configured to convert async
131
+ * errors into unhandled promise rejections by default, so if you need to change
132
+ * that you can use its {@link Job.asyncCatch `.asyncCatch()`} method.
133
+ *
134
+ * @returns The new root job.
135
+ *
136
+ * @remarks If your project customizes the root job in some way(s), you will
137
+ * probably want a function to do that, so you can use it both in tests and at
138
+ * runtime. (e.g. `myInit(newJob())` in tests, and `myInit(root)` at runtime.)
139
+ *
140
+ * @category Jobs
141
+ */
142
+ declare function newRoot(): Job<unknown>;
83
143
 
84
144
  /**
85
145
  * Convert a (possible) promise to something you can `yield *to()` in a job
@@ -653,4 +713,4 @@ declare function task<T, A extends any[], C, D extends {
653
713
  value?: (this: C, ...args: A) => StartObj<T>;
654
714
  }>(clsOrProto: any, name: string | symbol, desc: D): D;
655
715
 
656
- export { AnyFunction, Backpressure, CleanupFn, DisposeFn, type Emitter, Job, type MockSource, OptionalCleanup, Sink, Source, StartFn, StartObj, Stream, Transformer, Yielding, abortSignal, concat, concatAll, concatMap, defer, detached, emitter, empty, filter, fromAsyncIterable, fromDomEvent, fromIterable, fromPromise, fromSubscribe, fromValue, getJob, interval, isJobActive, lazy, makeJob, map, merge, mergeAll, mergeMap, mockSource, must, nativePromise, never, restarting, share, skip, skipUntil, skipWhile, slack, sleep, start, switchAll, switchMap, take, takeUntil, takeWhile, task, timeout, to };
716
+ export { AnyFunction, Backpressure, CleanupFn, DisposeFn, type Emitter, Job, type MockSource, OptionalCleanup, Sink, Source, StartFn, StartObj, Stream, Transformer, Yielding, abortSignal, concat, concatAll, concatMap, defer, detached, emitter, empty, filter, fromAsyncIterable, fromDomEvent, fromIterable, fromPromise, fromSubscribe, fromValue, getJob, interval, isJobActive, lazy, makeJob, map, merge, mergeAll, mergeMap, mockSource, must, nativePromise, never, newRoot, restarting, root, share, skip, skipUntil, skipWhile, slack, sleep, start, switchAll, switchMap, take, takeUntil, takeWhile, task, timeout, to };
package/dist/mod.mjs CHANGED
@@ -1,6 +1,8 @@
1
- import { d as defer, i as isFunction } from './utils-P0JEpWXG.mjs';
2
- import { r as resolver, a as rejecter, b as resolve, I as IsStream, c as backpressure, m as must, s as start, g as getJob, n as noop, t as throttle, d as detached, i as isCancel, e as isUnhandled, f as markHandled, h as isError, j as connect, k as fulfillPromise, l as callOrWait, o as restarting, p as current, q as mustBeSourceOrSignal, u as isValue } from './call-or-wait-DpJBh_pS.mjs';
3
- export { z as CancelError, C as CancelResult, E as ErrorResult, V as ValueResult, K as abortSignal, F as compose, x as getResult, G as into, w as isHandled, H as isJobActive, B as makeJob, A as nativePromise, D as pipe, y as propagateResult, v as reject, L as task, J as timeout } from './call-or-wait-DpJBh_pS.mjs';
1
+ import { d as defer, i as isFunction } from './utils-cyEhnyp7.mjs';
2
+ import { r as resolver, a as rejecter, b as resolve, m as must, s as start, g as getJob, n as noop, c as root, i as isCancel, d as isUnhandled, e as markHandled, f as isError, h as fulfillPromise, j as restarting, k as currentCell, l as isValue } from './jobutils-Dvu-e99o.mjs';
3
+ export { u as CancelError, C as CancelResult, E as ErrorResult, V as ValueResult, B as abortSignal, x as detached, q as getResult, p as isHandled, z as isJobActive, w as makeJob, v as nativePromise, y as newRoot, t as propagateResult, o as reject, D as task, A as timeout } from './jobutils-Dvu-e99o.mjs';
4
+ import { I as IsStream, b as backpressure, t as throttle, c as connect, a as callOrWait, m as mustBeSourceOrSignal } from './call-or-wait-EzXJX5Dq.mjs';
5
+ export { d as compose, i as into, p as pipe } from './call-or-wait-EzXJX5Dq.mjs';
4
6
 
5
7
  function* to(p) {
6
8
  return yield (res) => Promise.resolve(p).then(resolver(res), rejecter(res));
@@ -189,7 +191,7 @@ function share(source) {
189
191
  defer(produce);
190
192
  });
191
193
  if (links.size === 1) {
192
- uplink = detached.connect(source, (v) => {
194
+ uplink = root.connect(source, (v) => {
193
195
  for (const [s, c] of links)
194
196
  try {
195
197
  s(v);
@@ -274,10 +276,10 @@ function forEach(src, sink, inlet) {
274
276
  return (src2) => forEach(src2, sink, inlet);
275
277
  }
276
278
  function recalcWhen(fnOrKey, fn) {
277
- current.cell?.recalcWhen(fnOrKey, fn);
279
+ currentCell?.recalcWhen(fnOrKey, fn);
278
280
  }
279
281
  function isObserved() {
280
- return current.cell?.isObserved();
282
+ return currentCell?.isObserved();
281
283
  }
282
284
 
283
285
  function concat(sources) {
@@ -369,7 +371,7 @@ function slack(size, dropped = noop) {
369
371
  conn.connect(src, (v) => {
370
372
  buffer.push(v);
371
373
  if (!draining && ready())
372
- return drain();
374
+ return void drain();
373
375
  while (buffer.length > max) {
374
376
  dropped(size < 0 ? buffer.pop() : buffer.shift());
375
377
  }
@@ -399,6 +401,7 @@ function slack(size, dropped = noop) {
399
401
  } finally {
400
402
  draining = false;
401
403
  }
404
+ return false;
402
405
  }
403
406
  return IsStream;
404
407
  };
@@ -438,5 +441,4 @@ function takeWhile(condition) {
438
441
  };
439
442
  }
440
443
 
441
- export { IsStream, backpressure, concat, concatAll, concatMap, connect, defer, detached, each, emitter, empty, filter, forEach, fromAsyncIterable, fromDomEvent, fromIterable, fromPromise, fromSubscribe, fromValue, fulfillPromise, getJob, interval, isCancel, isError, isObserved, isUnhandled, isValue, lazy, map, markHandled, merge, mergeAll, mergeMap, mockSource, must, never, next, noop, recalcWhen, rejecter, resolve, resolver, restarting, share, skip, skipUntil, skipWhile, slack, sleep, start, switchAll, switchMap, take, takeUntil, takeWhile, throttle, to };
442
- //# sourceMappingURL=mod.mjs.map
444
+ export { IsStream, backpressure, concat, concatAll, concatMap, connect, defer, each, emitter, empty, filter, forEach, fromAsyncIterable, fromDomEvent, fromIterable, fromPromise, fromSubscribe, fromValue, fulfillPromise, getJob, interval, isCancel, isError, isObserved, isUnhandled, isValue, lazy, map, markHandled, merge, mergeAll, mergeMap, mockSource, must, never, next, noop, recalcWhen, rejecter, resolve, resolver, restarting, root, share, skip, skipUntil, skipWhile, slack, sleep, start, switchAll, switchMap, take, takeUntil, takeWhile, throttle, to };
@@ -0,0 +1,109 @@
1
+ import { Y as Yielding } from './types-N2ua11te.js';
2
+
3
+ /**
4
+ * Tools for sharing tasks, values, services, etc., especially across job
5
+ * boundaries.
6
+ *
7
+ * @module uneventful/shared
8
+ */
9
+
10
+ /**
11
+ * Wrap a factory function to create a singleton service accessor
12
+ *
13
+ * The returned function, when called, will run the factory in a new job and
14
+ * cache the result. The job the factory ran in will end when the {@link root}
15
+ * job does, after which the cached result will be cleared.
16
+ *
17
+ * @param factory A function returning whatever result you want to share: a
18
+ * value, a function, an object, etc. It will be called at most once per root
19
+ * job lifetime, in a job that is an immediate child of the root job.
20
+ *
21
+ * (Note: if your factory is a native generator function, it is automatically
22
+ * wrapped with {@link fork}() so that its job will not end when the generator
23
+ * ends, and the result can be waited on by multiple callers. If your factory
24
+ * is *not* a native generator function but still returns a generator to produce
25
+ * an async result, you should wrap that generator with {@link fork} before
26
+ * returning it.)
27
+ *
28
+ * @remarks Note that if you want your code to be testable with {@link newRoot},
29
+ * you should avoid storing the *result* of calling the service accessor
30
+ * anywhere it can outlive the root job, since you will otherwise end up with a
31
+ * stale reference to the previous service instance *and* fail to initialize the
32
+ * new instance.
33
+ *
34
+ * Your services can detect this scenario, however, by having the factory wrap
35
+ * its return value with {@link expiring}(), which will make any access to a
36
+ * saved service value throw a TypeError after the root job ends. (Note that
37
+ * such a thing should not be necessary in your production builds, however,
38
+ * since at runtime you will normally only ever have one root job.)
39
+ */
40
+ declare function service<T>(factory: () => T): () => T;
41
+ /**
42
+ * Proxy an object so it "expires" (becomes inaccessible) with the calling job.
43
+ *
44
+ * Any attempts to use the returned object after the job ends or restarts (other
45
+ * than to check its `typeof`) will result in a TypeError.
46
+ *
47
+ * Note: your runtime environment must support `Proxy.revocable()`.
48
+ */
49
+ declare function expiring<T extends object>(obj: T): T;
50
+ /**
51
+ * Wrap a generator, generator function, or generator method to run in parallel
52
+ * and have a result that can be waited on in parallel as well.
53
+ *
54
+ * Normally, when you `yield *` to a generator in a job function, you're
55
+ * *pausing* the current function until that generator is finished. And
56
+ * normally, this is what you *want*, because you're not trying to do things in
57
+ * parallel. But if you *do* want to do things in parallel, you need `fork`.
58
+ *
59
+ * Generators also can't normally be *waited on* in parallel either: if multiple
60
+ * jobs try to wait on an unfinished generator, the most likely result is an
61
+ * error or data corruption. (Because the extra `yield *` operations will make
62
+ * the generator think it's received data it was waiting for, causing all kinds
63
+ * of havoc.)
64
+ *
65
+ * So if you want a generator to either *run* in parallel or be *waited on* in
66
+ * parallel (or both), you need to `fork` it: either on the consuming side by
67
+ * wrapping a generator with `fork()`, or on the producing side by wrapping a
68
+ * generator function (or decorating a generator method).
69
+ *
70
+ * When called with a generator, `fork` returns a wrapped generator; when called
71
+ * with a function, it returns a wrapped version of the function that will fork
72
+ * its results. And when used as a decorator (`@fork`, compatible with both
73
+ * TC39 and legacy decorator protocols), it wraps a method to fork its result as
74
+ * well.
75
+ *
76
+ * It is safe to call `fork()` more than once on the same generator, or to
77
+ * `fork()` an already-forked generator: the result will always be the same as
78
+ * the original fork.
79
+ *
80
+ * @remarks Note that while you can *also* make a generator run or be waitable
81
+ * in parallel using e.g. `start()`, the critical difference is in when resource
82
+ * cleanup happens. If you `start()` the generator (or wrap the generator
83
+ * function with `task`), its resources will be cleaned up when the generator
84
+ * function exits.
85
+ *
86
+ * With `yield*`, however (with or without `fork`), the resources are cleaned up
87
+ * when the original *calling* job ends. And this is what you want when the
88
+ * generator's return value is some kind of resource using other active
89
+ * resources (such as event listeners rules, etc.) that need to *remain* active
90
+ * for the caller.
91
+ *
92
+ * (If you're familiar with the Effection framework, you may recognize this as
93
+ * the difference between "actions" and "resources": in Uneventful we use
94
+ * `start()` or `task()` for generators that return the result of an action, and
95
+ * `fork` for generators that return a resource that will be owned by the
96
+ * calling job.)
97
+ */
98
+ declare function fork<T>(gen: Yielding<T>): Yielding<T>;
99
+ declare function fork<T, F extends (...args: any[]) => Yielding<T>>(genFunc: F): F;
100
+ /** @hidden TC39 decorator */
101
+ declare function fork<T, F extends (...args: any[]) => Yielding<T>>(genFunc: F, ctx: {
102
+ kind: "method";
103
+ }): F;
104
+ /** @hidden legacy decorator */
105
+ declare function fork<T, F extends (...args: any[]) => Yielding<T>, D extends {
106
+ value?: F;
107
+ }>(clsOrProto: any, name: string | symbol, desc: D): D;
108
+
109
+ export { expiring, fork, service };