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