@dxos/async 0.8.4-main.f9ba587 → 0.8.4-main.fcfe5033a5

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 (67) hide show
  1. package/dist/lib/browser/index.mjs +318 -210
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node-esm/index.mjs +318 -210
  5. package/dist/lib/node-esm/index.mjs.map +4 -4
  6. package/dist/lib/node-esm/meta.json +1 -1
  7. package/dist/types/src/callback.d.ts +2 -1
  8. package/dist/types/src/callback.d.ts.map +1 -1
  9. package/dist/types/src/chain.d.ts +1 -1
  10. package/dist/types/src/chain.d.ts.map +1 -1
  11. package/dist/types/src/cleanup.d.ts +3 -3
  12. package/dist/types/src/cleanup.d.ts.map +1 -1
  13. package/dist/types/src/debounce.d.ts +37 -3
  14. package/dist/types/src/debounce.d.ts.map +1 -1
  15. package/dist/types/src/index.d.ts +0 -5
  16. package/dist/types/src/index.d.ts.map +1 -1
  17. package/dist/types/src/observable-value.d.ts.map +1 -1
  18. package/dist/types/src/persistent-lifecycle.d.ts +2 -2
  19. package/dist/types/src/persistent-lifecycle.d.ts.map +1 -1
  20. package/dist/types/src/task-scheduling.d.ts +29 -1
  21. package/dist/types/src/task-scheduling.d.ts.map +1 -1
  22. package/dist/types/src/testing.d.ts +13 -0
  23. package/dist/types/src/testing.d.ts.map +1 -1
  24. package/dist/types/src/timeout.d.ts +2 -2
  25. package/dist/types/src/timeout.d.ts.map +1 -1
  26. package/dist/types/src/trigger.d.ts +11 -0
  27. package/dist/types/src/trigger.d.ts.map +1 -1
  28. package/dist/types/tsconfig.tsbuildinfo +1 -1
  29. package/package.json +13 -9
  30. package/src/callback.ts +3 -3
  31. package/src/chain.ts +1 -1
  32. package/src/cleanup.ts +10 -7
  33. package/src/debounce.test.ts +69 -12
  34. package/src/debounce.ts +88 -14
  35. package/src/event-emitter.test.ts +1 -1
  36. package/src/index.ts +0 -5
  37. package/src/observable-value.test.ts +1 -1
  38. package/src/observable-value.ts +4 -2
  39. package/src/persistent-lifecycle.test.ts +1 -1
  40. package/src/persistent-lifecycle.ts +2 -2
  41. package/src/task-scheduling.ts +95 -1
  42. package/src/testing.test.ts +41 -1
  43. package/src/testing.ts +53 -0
  44. package/src/timeout.ts +27 -29
  45. package/src/trigger.ts +58 -1
  46. package/src/update-scheduler.ts +1 -1
  47. package/dist/types/src/latch.d.ts +0 -11
  48. package/dist/types/src/latch.d.ts.map +0 -1
  49. package/dist/types/src/sink.d.ts +0 -6
  50. package/dist/types/src/sink.d.ts.map +0 -1
  51. package/dist/types/src/throttle.d.ts +0 -2
  52. package/dist/types/src/throttle.d.ts.map +0 -1
  53. package/dist/types/src/throttle.test.d.ts +0 -2
  54. package/dist/types/src/throttle.test.d.ts.map +0 -1
  55. package/dist/types/src/types.d.ts +0 -2
  56. package/dist/types/src/types.d.ts.map +0 -1
  57. package/dist/types/src/until.d.ts +0 -14
  58. package/dist/types/src/until.d.ts.map +0 -1
  59. package/dist/types/src/until.test.d.ts +0 -2
  60. package/dist/types/src/until.test.d.ts.map +0 -1
  61. package/src/latch.ts +0 -60
  62. package/src/sink.ts +0 -26
  63. package/src/throttle.test.ts +0 -65
  64. package/src/throttle.ts +0 -14
  65. package/src/types.ts +0 -5
  66. package/src/until.test.ts +0 -47
  67. package/src/until.ts +0 -58
@@ -1,5 +1,5 @@
1
1
  // src/callback.ts
2
- var createPromiseFromCallback = (run) => new Promise((resolve, reject) => {
2
+ var promiseFromCallback = (run) => new Promise((resolve, reject) => {
3
3
  run((error, value) => {
4
4
  if (error) {
5
5
  reject(error);
@@ -10,9 +10,9 @@ var createPromiseFromCallback = (run) => new Promise((resolve, reject) => {
10
10
  });
11
11
 
12
12
  // src/chain.ts
13
- var asyncChain = (chain) => async (elements) => {
13
+ var chain = (chain2) => async (elements) => {
14
14
  let result = await elements;
15
- for (const part of chain) {
15
+ for (const part of chain2) {
16
16
  result = await Promise.all(result.map(async (element) => await part(element)));
17
17
  }
18
18
  return result;
@@ -22,7 +22,7 @@ var asyncChain = (chain) => async (elements) => {
22
22
  import { ComplexMap } from "@dxos/util";
23
23
  var combine = (...cleanupFns) => {
24
24
  return () => {
25
- cleanupFns.flat().forEach((cleanupFn) => cleanupFn());
25
+ cleanupFns.flat().filter((f) => typeof f === "function").forEach((cleanupFn) => cleanupFn());
26
26
  };
27
27
  };
28
28
  var timeout = (cb, ms = 0) => {
@@ -33,16 +33,14 @@ var interval = (cb, ms) => {
33
33
  const t = setInterval(cb, ms);
34
34
  return () => clearInterval(t);
35
35
  };
36
- function addEventListener(target, type, listener, options) {
36
+ var addEventListener = (target, type, listener, options) => {
37
37
  target.addEventListener(type, listener, options);
38
38
  return () => target.removeEventListener(type, listener, options);
39
- }
39
+ };
40
40
  var SubscriptionList = class {
41
- constructor() {
42
- this._cleanups = [];
43
- }
44
- add(cb) {
45
- this._cleanups.push(cb);
41
+ _cleanups = [];
42
+ add(...cb) {
43
+ this._cleanups.push(...cb);
46
44
  return this;
47
45
  }
48
46
  clear() {
@@ -51,6 +49,7 @@ var SubscriptionList = class {
51
49
  }
52
50
  };
53
51
  var SubscriptionSet = class {
52
+ _cleanupMap;
54
53
  constructor(keyProjection) {
55
54
  this._cleanupMap = new ComplexMap(keyProjection);
56
55
  }
@@ -64,32 +63,56 @@ var SubscriptionSet = class {
64
63
  }
65
64
  };
66
65
 
67
- // src/throttle.ts
68
- var throttle = (cb, wait = 100) => {
69
- let lastCall = 0;
66
+ // src/debounce.ts
67
+ var delay = (cb, delay2 = 100) => {
68
+ let pending = false;
70
69
  return (...args) => {
71
- const now = Date.now();
72
- if (now - lastCall >= wait) {
73
- cb(...args);
74
- lastCall = now;
70
+ if (pending) {
71
+ return;
75
72
  }
73
+ pending = true;
74
+ setTimeout(() => {
75
+ try {
76
+ cb(...args);
77
+ } finally {
78
+ pending = false;
79
+ }
80
+ }, delay2);
76
81
  };
77
82
  };
78
-
79
- // src/debounce.ts
80
- var debounce = (cb, wait = 100) => {
83
+ var debounce = (cb, delay2 = 100) => {
81
84
  let t;
82
85
  return (...args) => {
83
86
  clearTimeout(t);
84
- t = setTimeout(() => cb(...args), wait);
87
+ t = setTimeout(() => cb(...args), delay2);
85
88
  };
86
89
  };
87
- var debounceAndThrottle = (cb, wait = 100) => {
88
- const debounced = debounce(cb, wait);
89
- const throttled = throttle(cb, wait);
90
+ var throttle = (cb, delay2 = 100) => {
91
+ let lastCall = 0;
90
92
  return (...args) => {
91
- debounced(...args);
92
- throttled(...args);
93
+ const now = Date.now();
94
+ if (now - lastCall >= delay2) {
95
+ cb(...args);
96
+ lastCall = now;
97
+ }
98
+ };
99
+ };
100
+ var debounceAndThrottle = (cb, delay2 = 100) => {
101
+ let timeout2;
102
+ let lastCall = 0;
103
+ return (...args) => {
104
+ const now = Date.now();
105
+ const delta = now - lastCall;
106
+ clearTimeout(timeout2);
107
+ if (delta >= delay2) {
108
+ cb(...args);
109
+ lastCall = now;
110
+ } else {
111
+ timeout2 = setTimeout(() => {
112
+ cb(...args);
113
+ lastCall = Date.now();
114
+ }, delay2 - delta);
115
+ }
93
116
  };
94
117
  };
95
118
 
@@ -124,8 +147,28 @@ var sleep = (ms) => {
124
147
  sleeper();
125
148
  });
126
149
  };
150
+ var sleepWithContext = (ctx, ms) => {
151
+ const error = new ContextDisposedError();
152
+ return new Promise((resolve, reject) => {
153
+ if (ctx.disposed) {
154
+ reject(error);
155
+ return;
156
+ }
157
+ const timeout2 = setTimeout(() => {
158
+ clearDispose();
159
+ resolve();
160
+ }, ms);
161
+ const clearDispose = ctx.onDispose(() => {
162
+ clearTimeout(timeout2);
163
+ reject(error);
164
+ });
165
+ });
166
+ };
127
167
  var asyncReturn = () => sleep(0);
128
168
  var asyncTimeout = async (promise, timeout2, err) => {
169
+ if (typeof promise === "function") {
170
+ throw new Error("First argument must be a promise.");
171
+ }
129
172
  let timeoutId;
130
173
  const throwable = err === void 0 || typeof err === "string" ? new TimeoutError(timeout2, err) : err;
131
174
  const timeoutPromise = new Promise((resolve, reject) => {
@@ -134,9 +177,8 @@ var asyncTimeout = async (promise, timeout2, err) => {
134
177
  }, timeout2);
135
178
  unrefTimeout(timeoutId);
136
179
  });
137
- const conditionTimeout = typeof promise === "function" ? createPromiseFromCallback(promise) : promise;
138
180
  return await Promise.race([
139
- conditionTimeout,
181
+ promise,
140
182
  timeoutPromise
141
183
  ]).finally(() => {
142
184
  clearTimeout(timeoutId);
@@ -147,23 +189,6 @@ var unrefTimeout = (timeoutId) => {
147
189
  timeoutId.unref();
148
190
  }
149
191
  };
150
- var sleepWithContext = (ctx, ms) => {
151
- const error = new ContextDisposedError();
152
- return new Promise((resolve, reject) => {
153
- if (ctx.disposed) {
154
- reject(error);
155
- return;
156
- }
157
- const timeout2 = setTimeout(() => {
158
- clearDispose();
159
- resolve();
160
- }, ms);
161
- const clearDispose = ctx.onDispose(() => {
162
- clearTimeout(timeout2);
163
- reject(error);
164
- });
165
- });
166
- };
167
192
 
168
193
  // src/event-emitter.ts
169
194
  var onEvent = (eventEmitter, eventName, callback) => {
@@ -193,10 +218,6 @@ import { Context } from "@dxos/context";
193
218
  var __dxlog_file = "/__w/dxos/dxos/packages/common/async/src/events.ts";
194
219
  var DO_NOT_ERROR_ON_ASYNC_CALLBACK = true;
195
220
  var Event = class _Event {
196
- constructor() {
197
- this._listeners = /* @__PURE__ */ new Set();
198
- this._effects = /* @__PURE__ */ new Set();
199
- }
200
221
  /**
201
222
  * Wrap objects that have on/off style event emitters.
202
223
  */
@@ -209,6 +230,8 @@ var Event = class _Event {
209
230
  });
210
231
  return event;
211
232
  }
233
+ _listeners = /* @__PURE__ */ new Set();
234
+ _effects = /* @__PURE__ */ new Set();
212
235
  /**
213
236
  * Emit an event.
214
237
  * In most cases should only be called by the class or entity containing the event.
@@ -452,11 +475,15 @@ var Event = class _Event {
452
475
  }
453
476
  };
454
477
  var EventListener = class {
478
+ ctx;
479
+ once;
480
+ weak;
481
+ callback;
482
+ _clearDispose = void 0;
455
483
  constructor(event, listener, ctx, once, weak) {
456
484
  this.ctx = ctx;
457
485
  this.once = once;
458
486
  this.weak = weak;
459
- this._clearDispose = void 0;
460
487
  this._clearDispose = ctx.onDispose(() => {
461
488
  event._removeListener(this);
462
489
  });
@@ -516,65 +543,13 @@ var weakListeners = () => {
516
543
  };
517
544
  };
518
545
 
519
- // src/latch.ts
520
- import { invariant } from "@dxos/invariant";
521
- var __dxlog_file2 = "/__w/dxos/dxos/packages/common/async/src/latch.ts";
522
- var latch = ({ count = 1, timeout: timeout2 } = {}) => {
523
- invariant(count >= 0, void 0, {
524
- F: __dxlog_file2,
525
- L: 19,
526
- S: void 0,
527
- A: [
528
- "count >= 0",
529
- ""
530
- ]
531
- });
532
- let t;
533
- let doResolve;
534
- let doReject;
535
- const promise = new Promise((resolve, reject) => {
536
- doResolve = (value) => {
537
- clearTimeout(t);
538
- resolve(value);
539
- };
540
- doReject = (err) => {
541
- clearTimeout(t);
542
- reject(err);
543
- };
544
- });
545
- if (count === 0) {
546
- setTimeout(() => {
547
- doResolve(0);
548
- });
549
- } else {
550
- if (timeout2) {
551
- t = setTimeout(() => {
552
- doReject(new Error(`Timed out after ${timeout2.toLocaleString()}ms`));
553
- }, timeout2);
554
- }
555
- }
556
- let i = 0;
557
- return [
558
- async () => await promise,
559
- () => {
560
- if (++i === count) {
561
- doResolve(i);
562
- }
563
- return i;
564
- },
565
- (err) => doReject(err)
566
- ];
567
- };
568
-
569
546
  // src/mutex.ts
570
547
  import "@dxos/util";
571
548
  import { warnAfterTimeout } from "@dxos/debug";
572
549
  var Mutex = class {
573
- constructor() {
574
- this._queue = Promise.resolve();
575
- this._queueLength = 0;
576
- this._tag = null;
577
- }
550
+ _queue = Promise.resolve();
551
+ _queueLength = 0;
552
+ _tag = null;
578
553
  get tag() {
579
554
  return this._tag;
580
555
  }
@@ -620,6 +595,7 @@ var Mutex = class {
620
595
  }
621
596
  };
622
597
  var MutexGuard = class {
598
+ _release;
623
599
  constructor(_release) {
624
600
  this._release = _release;
625
601
  }
@@ -633,7 +609,7 @@ var MutexGuard = class {
633
609
  this.release();
634
610
  }
635
611
  };
636
- var classMutexSymbol = Symbol("class-mutex");
612
+ var classMutexSymbol = /* @__PURE__ */ Symbol("class-mutex");
637
613
  var FORCE_DISABLE_WARNING = false;
638
614
  var enableWarning = !FORCE_DISABLE_WARNING && globalThis.mochaExecutor;
639
615
  var synchronized = (target, propertyName, descriptor) => {
@@ -663,6 +639,8 @@ import Observable from "zen-observable";
663
639
  import PushStream from "zen-push";
664
640
 
665
641
  // src/trigger.ts
642
+ import { invariant } from "@dxos/invariant";
643
+ var __dxlog_file2 = "/__w/dxos/dxos/packages/common/async/src/trigger.ts";
666
644
  var trigger = (timeout2) => {
667
645
  let callback;
668
646
  const promise = new Promise((resolve, reject) => {
@@ -678,18 +656,22 @@ var trigger = (timeout2) => {
678
656
  resolver
679
657
  ];
680
658
  };
681
- var TriggerState = /* @__PURE__ */ function(TriggerState2) {
659
+ var TriggerState = /* @__PURE__ */ (function(TriggerState2) {
682
660
  TriggerState2["WAITING"] = "WAITING";
683
661
  TriggerState2["RESOLVED"] = "RESOLVED";
684
662
  TriggerState2["REJECTED"] = "REJECTED";
685
663
  return TriggerState2;
686
- }({});
664
+ })({});
687
665
  var Trigger = class {
666
+ _options;
667
+ _promise;
668
+ _resolve;
669
+ _reject;
670
+ _state = "WAITING";
688
671
  constructor(_options = {
689
672
  autoReset: false
690
673
  }) {
691
674
  this._options = _options;
692
- this._state = "WAITING";
693
675
  this.reset();
694
676
  }
695
677
  get state() {
@@ -749,23 +731,61 @@ var Trigger = class {
749
731
  return this;
750
732
  }
751
733
  };
734
+ var latch = ({ count = 1, timeout: timeout2 } = {}) => {
735
+ invariant(count >= 0, void 0, {
736
+ F: __dxlog_file2,
737
+ L: 139,
738
+ S: void 0,
739
+ A: [
740
+ "count >= 0",
741
+ ""
742
+ ]
743
+ });
744
+ let t;
745
+ let doResolve;
746
+ let doReject;
747
+ const promise = new Promise((resolve, reject) => {
748
+ doResolve = (value) => {
749
+ clearTimeout(t);
750
+ resolve(value);
751
+ };
752
+ doReject = (err) => {
753
+ clearTimeout(t);
754
+ reject(err);
755
+ };
756
+ });
757
+ if (count === 0) {
758
+ setTimeout(() => {
759
+ doResolve(0);
760
+ });
761
+ } else {
762
+ if (timeout2) {
763
+ t = setTimeout(() => {
764
+ doReject(new Error(`Timed out after ${timeout2.toLocaleString()}ms`));
765
+ }, timeout2);
766
+ }
767
+ }
768
+ let i = 0;
769
+ return [
770
+ async () => await promise,
771
+ () => {
772
+ if (++i === count) {
773
+ doResolve(i);
774
+ }
775
+ return i;
776
+ },
777
+ (err) => doReject(err)
778
+ ];
779
+ };
752
780
 
753
781
  // src/observable.ts
754
782
  var MulticastObservable = class _MulticastObservable extends Observable {
783
+ _value;
784
+ _observers = /* @__PURE__ */ new Set();
785
+ _observable;
786
+ _completed = new Trigger();
755
787
  constructor(subscriber, _value) {
756
- super((observer) => this._subscribe(observer)), this._value = _value, this._observers = /* @__PURE__ */ new Set(), this._completed = new Trigger(), this._handlers = {
757
- next: (value) => {
758
- this._value = value;
759
- this._observers.forEach((observer) => observer.next?.(value));
760
- },
761
- error: (err) => {
762
- this._observers.forEach((observer) => observer.error?.(err));
763
- },
764
- complete: () => {
765
- this._completed.wake();
766
- this._observers.forEach((observer) => observer.complete?.());
767
- }
768
- };
788
+ super((observer) => this._subscribe(observer)), this._value = _value;
769
789
  this._observable = typeof subscriber === "function" ? new Observable(subscriber) : subscriber;
770
790
  this._observable.subscribe(this._handlers);
771
791
  }
@@ -849,18 +869,30 @@ var MulticastObservable = class _MulticastObservable extends Observable {
849
869
  this._observers.delete(observer);
850
870
  };
851
871
  }
872
+ _handlers = {
873
+ next: (value) => {
874
+ this._value = value;
875
+ this._observers.forEach((observer) => observer.next?.(value));
876
+ },
877
+ error: (err) => {
878
+ this._observers.forEach((observer) => observer.error?.(err));
879
+ },
880
+ complete: () => {
881
+ this._completed.wake();
882
+ this._observers.forEach((observer) => observer.complete?.());
883
+ }
884
+ };
852
885
  };
853
886
  var EMPTY_OBSERVABLE = MulticastObservable.of(null);
854
887
 
855
888
  // src/observable-value.ts
856
889
  import { createSetDispatch } from "@dxos/util";
857
890
  var ObservableProvider = class {
858
- constructor() {
859
- this._handlers = /* @__PURE__ */ new Set();
860
- this._proxy = createSetDispatch({
861
- handlers: this._handlers
862
- });
863
- }
891
+ _handlers = /* @__PURE__ */ new Set();
892
+ _proxy = createSetDispatch({
893
+ handlers: this._handlers
894
+ });
895
+ _value;
864
896
  /**
865
897
  * Proxy used to dispatch callbacks to each subscription.
866
898
  */
@@ -881,8 +913,10 @@ var ObservableProvider = class {
881
913
  }
882
914
  };
883
915
  var CancellableObservableProvider = class extends ObservableProvider {
916
+ _handleCancel;
917
+ _cancelled = false;
884
918
  constructor(_handleCancel) {
885
- super(), this._handleCancel = _handleCancel, this._cancelled = false;
919
+ super(), this._handleCancel = _handleCancel;
886
920
  }
887
921
  get cancelled() {
888
922
  return this._cancelled;
@@ -903,7 +937,7 @@ import { warnAfterTimeout as warnAfterTimeout2 } from "@dxos/debug";
903
937
  import { log as log2 } from "@dxos/log";
904
938
 
905
939
  // src/task-scheduling.ts
906
- import { ContextDisposedError as ContextDisposedError2 } from "@dxos/context";
940
+ import { Context as Context2, ContextDisposedError as ContextDisposedError2 } from "@dxos/context";
907
941
  import { StackTrace as StackTrace2 } from "@dxos/debug";
908
942
 
909
943
  // src/track-leaks.ts
@@ -912,7 +946,7 @@ import { log } from "@dxos/log";
912
946
  var __dxlog_file3 = "/__w/dxos/dxos/packages/common/async/src/track-leaks.ts";
913
947
  var enabled = typeof process !== "undefined" && !!process.env.DX_TRACK_LEAKS;
914
948
  var openResources = /* @__PURE__ */ new Set();
915
- var handleSymbol = Symbol("checkLeaksHandle");
949
+ var handleSymbol = /* @__PURE__ */ Symbol("checkLeaksHandle");
916
950
  var trackResource = (resourceProvider) => {
917
951
  if (!enabled) {
918
952
  return () => {
@@ -991,13 +1025,16 @@ if (enabled) {
991
1025
  }
992
1026
 
993
1027
  // src/task-scheduling.ts
1028
+ var __dxlog_file4 = "/__w/dxos/dxos/packages/common/async/src/task-scheduling.ts";
994
1029
  var DeferredTask = class {
1030
+ _ctx;
1031
+ _callback;
1032
+ _scheduled = false;
1033
+ _currentTask = null;
1034
+ _nextTask = new Trigger();
995
1035
  constructor(_ctx, _callback) {
996
1036
  this._ctx = _ctx;
997
1037
  this._callback = _callback;
998
- this._scheduled = false;
999
- this._currentTask = null;
1000
- this._nextTask = new Trigger();
1001
1038
  }
1002
1039
  get scheduled() {
1003
1040
  return this._scheduled;
@@ -1038,6 +1075,82 @@ var DeferredTask = class {
1038
1075
  await this._currentTask;
1039
1076
  }
1040
1077
  };
1078
+ var AsyncTask = class {
1079
+ #callback;
1080
+ #ctx = void 0;
1081
+ #scheduled = false;
1082
+ #currentTask = null;
1083
+ #nextTask = new Trigger();
1084
+ constructor(callback) {
1085
+ this.#callback = callback;
1086
+ }
1087
+ get scheduled() {
1088
+ return this.#scheduled;
1089
+ }
1090
+ /**
1091
+ * Context of the resource that owns the task.
1092
+ * When the context is disposed, the task is cancelled and cannot be scheduled again.
1093
+ */
1094
+ open() {
1095
+ this.#ctx = new Context2(void 0, {
1096
+ F: __dxlog_file4,
1097
+ L: 102
1098
+ });
1099
+ }
1100
+ /**
1101
+ * Closes the task and waits for it to finish if it is running.
1102
+ */
1103
+ async close() {
1104
+ await this.#ctx?.dispose();
1105
+ await this.join();
1106
+ this.#ctx = void 0;
1107
+ }
1108
+ [Symbol.asyncDispose]() {
1109
+ return this.close();
1110
+ }
1111
+ /**
1112
+ * Schedule the task to run asynchronously.
1113
+ */
1114
+ // TODO(dmaretskyi): Add scheduleAt. Where the earlier time will override the later one.
1115
+ schedule() {
1116
+ if (!this.#ctx || this.#ctx.disposed) {
1117
+ throw new Error("AsyncTask not open");
1118
+ }
1119
+ if (this.#scheduled) {
1120
+ return;
1121
+ }
1122
+ scheduleTask(this.#ctx, async () => {
1123
+ await this.#currentTask;
1124
+ if (!this.#ctx || this.#ctx.disposed) {
1125
+ return;
1126
+ }
1127
+ this.#scheduled = false;
1128
+ const completionTrigger = this.#nextTask;
1129
+ this.#nextTask = new Trigger();
1130
+ this.#currentTask = runInContextAsync(this.#ctx, () => this.#callback()).then(() => {
1131
+ completionTrigger.wake();
1132
+ });
1133
+ });
1134
+ this.#scheduled = true;
1135
+ }
1136
+ /**
1137
+ * Schedule the task to run and wait for it to finish.
1138
+ */
1139
+ async runBlocking() {
1140
+ if (this.#ctx?.disposed) {
1141
+ throw new ContextDisposedError2();
1142
+ }
1143
+ this.schedule();
1144
+ await this.#nextTask.wait();
1145
+ }
1146
+ /**
1147
+ * Waits for the current task to finish if it is running.
1148
+ * Does not schedule a new task.
1149
+ */
1150
+ async join() {
1151
+ await this.#currentTask;
1152
+ }
1153
+ };
1041
1154
  var runInContext = (ctx, fn) => {
1042
1155
  try {
1043
1156
  fn();
@@ -1123,15 +1236,19 @@ function _ts_decorate(decorators, target, key, desc) {
1123
1236
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1124
1237
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1125
1238
  }
1126
- var __dxlog_file4 = "/__w/dxos/dxos/packages/common/async/src/persistent-lifecycle.ts";
1239
+ var __dxlog_file5 = "/__w/dxos/dxos/packages/common/async/src/persistent-lifecycle.ts";
1127
1240
  var INIT_RESTART_DELAY = 100;
1128
1241
  var DEFAULT_MAX_RESTART_DELAY = 5e3;
1129
1242
  var PersistentLifecycle = class extends Resource {
1243
+ _start;
1244
+ _stop;
1245
+ _onRestart;
1246
+ _maxRestartDelay;
1247
+ _currentState = void 0;
1248
+ _restartTask = void 0;
1249
+ _restartAfter = 0;
1130
1250
  constructor({ start, stop, onRestart, maxRestartDelay = DEFAULT_MAX_RESTART_DELAY }) {
1131
1251
  super();
1132
- this._currentState = void 0;
1133
- this._restartTask = void 0;
1134
- this._restartAfter = 0;
1135
1252
  this._start = start;
1136
1253
  this._stop = stop;
1137
1254
  this._onRestart = onRestart;
@@ -1148,7 +1265,7 @@ var PersistentLifecycle = class extends Resource {
1148
1265
  log2.warn("Restart failed", {
1149
1266
  err
1150
1267
  }, {
1151
- F: __dxlog_file4,
1268
+ F: __dxlog_file5,
1152
1269
  L: 72,
1153
1270
  S: this,
1154
1271
  C: (f, a) => f(...a)
@@ -1160,7 +1277,7 @@ var PersistentLifecycle = class extends Resource {
1160
1277
  log2.warn("Start failed", {
1161
1278
  err
1162
1279
  }, {
1163
- F: __dxlog_file4,
1280
+ F: __dxlog_file5,
1164
1281
  L: 78,
1165
1282
  S: this,
1166
1283
  C: (f, a) => f(...a)
@@ -1178,7 +1295,7 @@ var PersistentLifecycle = class extends Resource {
1178
1295
  log2(`restarting in ${this._restartAfter}ms`, {
1179
1296
  state: this._lifecycleState
1180
1297
  }, {
1181
- F: __dxlog_file4,
1298
+ F: __dxlog_file5,
1182
1299
  L: 91,
1183
1300
  S: this,
1184
1301
  C: (f, a) => f(...a)
@@ -1201,7 +1318,7 @@ var PersistentLifecycle = class extends Resource {
1201
1318
  await this._stop(this._currentState);
1202
1319
  } catch (err) {
1203
1320
  log2.catch(err, void 0, {
1204
- F: __dxlog_file4,
1321
+ F: __dxlog_file5,
1205
1322
  L: 113,
1206
1323
  S: this,
1207
1324
  C: (f, a) => f(...a)
@@ -1229,7 +1346,7 @@ _ts_decorate([
1229
1346
 
1230
1347
  // src/push-iterable.ts
1231
1348
  import { invariant as invariant2 } from "@dxos/invariant";
1232
- var __dxlog_file5 = "/__w/dxos/dxos/packages/common/async/src/push-iterable.ts";
1349
+ var __dxlog_file6 = "/__w/dxos/dxos/packages/common/async/src/push-iterable.ts";
1233
1350
  var makePushIterable = () => {
1234
1351
  const buf = [];
1235
1352
  const trigger2 = new Trigger({
@@ -1244,7 +1361,7 @@ var makePushIterable = () => {
1244
1361
  }
1245
1362
  const item = buf.shift();
1246
1363
  invariant2(item, void 0, {
1247
- F: __dxlog_file5,
1364
+ F: __dxlog_file6,
1248
1365
  L: 42,
1249
1366
  S: this,
1250
1367
  A: [
@@ -1293,20 +1410,6 @@ var makePushIterable = () => {
1293
1410
  };
1294
1411
  };
1295
1412
 
1296
- // src/sink.ts
1297
- var sink = (emitter, event, count = 1) => {
1298
- const [getPromise, resolve] = trigger();
1299
- let counter = 0;
1300
- const listener = () => {
1301
- if (++counter === count) {
1302
- emitter.off(event, listener);
1303
- resolve();
1304
- }
1305
- };
1306
- emitter.on(event, listener);
1307
- return getPromise();
1308
- };
1309
-
1310
1413
  // src/stream-to-array.ts
1311
1414
  var streamToArray = (stream) => {
1312
1415
  let deferred;
@@ -1352,11 +1455,6 @@ var streamToArray = (stream) => {
1352
1455
  // src/test-stream.ts
1353
1456
  import { Duplex } from "@dxos/node-std/stream";
1354
1457
  var TestStream = class extends Duplex {
1355
- constructor() {
1356
- super(...arguments);
1357
- this._received = Buffer.alloc(0);
1358
- this._onWrite = new Event();
1359
- }
1360
1458
  static async assertConnectivity(stream1, stream2, { timeout: timeout2 = 200 } = {}) {
1361
1459
  stream1.push("ping");
1362
1460
  stream2.push("pong");
@@ -1369,6 +1467,8 @@ var TestStream = class extends Duplex {
1369
1467
  })
1370
1468
  ]);
1371
1469
  }
1470
+ _received = Buffer.alloc(0);
1471
+ _onWrite = new Event();
1372
1472
  _write(chunk, encoding, callback) {
1373
1473
  this._received = Buffer.concat([
1374
1474
  this._received,
@@ -1410,13 +1510,48 @@ var waitForCondition = ({ condition, timeout: timeout2 = 0, interval: interval2
1410
1510
  timeout: timeout2
1411
1511
  });
1412
1512
  };
1513
+ var until = (cb, timeout2) => {
1514
+ return new Promise((resolve, reject) => {
1515
+ const t = timeout2 && setTimeout(() => {
1516
+ reject(new Error(`Timeout after ${t}ms`));
1517
+ }, timeout2);
1518
+ setTimeout(async () => {
1519
+ try {
1520
+ await cb((value) => {
1521
+ t && clearTimeout(t);
1522
+ resolve(value);
1523
+ }, (error) => {
1524
+ t && clearTimeout(t);
1525
+ reject(error);
1526
+ });
1527
+ } catch (err) {
1528
+ reject(err);
1529
+ }
1530
+ });
1531
+ });
1532
+ };
1533
+ var untilPromise = (cb) => cb();
1534
+ var untilError = (cb) => {
1535
+ return new Promise((resolve, reject) => {
1536
+ setTimeout(async () => {
1537
+ try {
1538
+ await cb();
1539
+ reject(new Error("No error was thrown."));
1540
+ } catch (err) {
1541
+ resolve(err);
1542
+ }
1543
+ });
1544
+ });
1545
+ };
1413
1546
 
1414
1547
  // src/timer.ts
1415
1548
  var Timer = class {
1549
+ _callback;
1550
+ _state = new Event();
1551
+ _timer;
1552
+ _count = 0;
1416
1553
  constructor(_callback) {
1417
1554
  this._callback = _callback;
1418
- this._state = new Event();
1419
- this._count = 0;
1420
1555
  }
1421
1556
  get state() {
1422
1557
  return this._state;
@@ -1459,51 +1594,23 @@ var Timer = class {
1459
1594
  }
1460
1595
  };
1461
1596
 
1462
- // src/until.ts
1463
- var until = (cb, timeout2) => {
1464
- return new Promise((resolve, reject) => {
1465
- const t = timeout2 && setTimeout(() => {
1466
- reject(new Error(`Timeout after ${t}ms`));
1467
- }, timeout2);
1468
- setTimeout(async () => {
1469
- try {
1470
- await cb((value) => {
1471
- t && clearTimeout(t);
1472
- resolve(value);
1473
- }, (error) => {
1474
- t && clearTimeout(t);
1475
- reject(error);
1476
- });
1477
- } catch (err) {
1478
- reject(err);
1479
- }
1480
- });
1481
- });
1482
- };
1483
- var untilPromise = (cb) => cb();
1484
- var untilError = (cb) => {
1485
- return new Promise((resolve, reject) => {
1486
- setTimeout(async () => {
1487
- try {
1488
- await cb();
1489
- reject(new Error("No error was thrown."));
1490
- } catch (err) {
1491
- resolve(err);
1492
- }
1493
- });
1494
- });
1495
- };
1496
-
1497
1597
  // src/update-scheduler.ts
1498
1598
  var TIME_PERIOD = 1e3;
1499
1599
  var UpdateScheduler = class {
1600
+ _ctx;
1601
+ _callback;
1602
+ _params;
1603
+ /**
1604
+ * Promise that resolves when the callback is done.
1605
+ * Never rejects.
1606
+ */
1607
+ _promise = null;
1608
+ _scheduled = false;
1609
+ _lastUpdateTime = -TIME_PERIOD;
1500
1610
  constructor(_ctx, _callback, _params = {}) {
1501
1611
  this._ctx = _ctx;
1502
1612
  this._callback = _callback;
1503
1613
  this._params = _params;
1504
- this._promise = null;
1505
- this._scheduled = false;
1506
- this._lastUpdateTime = -TIME_PERIOD;
1507
1614
  _ctx.onDispose(async () => {
1508
1615
  await this._promise;
1509
1616
  });
@@ -1516,13 +1623,13 @@ var UpdateScheduler = class {
1516
1623
  await this._promise;
1517
1624
  if (this._params.maxFrequency) {
1518
1625
  const now = performance.now();
1519
- const delay = this._lastUpdateTime + TIME_PERIOD / this._params.maxFrequency - now;
1520
- if (delay > 0) {
1626
+ const delay2 = this._lastUpdateTime + TIME_PERIOD / this._params.maxFrequency - now;
1627
+ if (delay2 > 0) {
1521
1628
  await new Promise((resolve) => {
1522
1629
  const timeoutId = setTimeout(() => {
1523
1630
  clearContext();
1524
1631
  resolve();
1525
- }, delay);
1632
+ }, delay2);
1526
1633
  const clearContext = this._ctx.onDispose(() => {
1527
1634
  clearTimeout(timeoutId);
1528
1635
  resolve();
@@ -1566,6 +1673,7 @@ var UpdateScheduler = class {
1566
1673
  }
1567
1674
  };
1568
1675
  export {
1676
+ AsyncTask,
1569
1677
  CancellableObservableProvider,
1570
1678
  DeferredTask,
1571
1679
  Event,
@@ -1586,26 +1694,26 @@ export {
1586
1694
  UpdateScheduler,
1587
1695
  addEventListener,
1588
1696
  addListener,
1589
- asyncChain,
1590
1697
  asyncReturn,
1591
1698
  asyncTimeout,
1699
+ chain,
1592
1700
  combine,
1593
- createPromiseFromCallback,
1594
1701
  debounce,
1595
1702
  debounceAndThrottle,
1703
+ delay,
1596
1704
  dumpLeaks,
1597
1705
  interval,
1598
1706
  latch,
1599
1707
  makePushIterable,
1600
1708
  observableError,
1601
1709
  onEvent,
1710
+ promiseFromCallback,
1602
1711
  runInContext,
1603
1712
  runInContextAsync,
1604
1713
  scheduleExponentialBackoffTaskInterval,
1605
1714
  scheduleMicroTask,
1606
1715
  scheduleTask,
1607
1716
  scheduleTaskInterval,
1608
- sink,
1609
1717
  sleep,
1610
1718
  sleepWithContext,
1611
1719
  streamToArray,