@dxos/async 0.8.4-main.c1de068 → 0.8.4-main.c351d160a8

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.
@@ -22,7 +22,7 @@ var chain = (chain2) => 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) => {
@@ -38,11 +38,9 @@ var addEventListener = (target, 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
  }
@@ -65,29 +64,55 @@ var SubscriptionSet = class {
65
64
  };
66
65
 
67
66
  // src/debounce.ts
68
- var debounce = (cb, delay = 100) => {
67
+ var delay = (cb, delay2 = 100) => {
68
+ let pending = false;
69
+ return (...args) => {
70
+ if (pending) {
71
+ return;
72
+ }
73
+ pending = true;
74
+ setTimeout(() => {
75
+ try {
76
+ cb(...args);
77
+ } finally {
78
+ pending = false;
79
+ }
80
+ }, delay2);
81
+ };
82
+ };
83
+ var debounce = (cb, delay2 = 100) => {
69
84
  let t;
70
85
  return (...args) => {
71
86
  clearTimeout(t);
72
- t = setTimeout(() => cb(...args), delay);
87
+ t = setTimeout(() => cb(...args), delay2);
73
88
  };
74
89
  };
75
- var throttle = (cb, delay = 100) => {
90
+ var throttle = (cb, delay2 = 100) => {
76
91
  let lastCall = 0;
77
92
  return (...args) => {
78
93
  const now = Date.now();
79
- if (now - lastCall >= delay) {
94
+ if (now - lastCall >= delay2) {
80
95
  cb(...args);
81
96
  lastCall = now;
82
97
  }
83
98
  };
84
99
  };
85
- var debounceAndThrottle = (cb, delay = 100) => {
86
- const debounced = debounce(cb, delay);
87
- const throttled = throttle(cb, delay);
100
+ var debounceAndThrottle = (cb, delay2 = 100) => {
101
+ let timeout2;
102
+ let lastCall = 0;
88
103
  return (...args) => {
89
- debounced(...args);
90
- throttled(...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
+ }
91
116
  };
92
117
  };
93
118
 
@@ -141,6 +166,9 @@ var sleepWithContext = (ctx, ms) => {
141
166
  };
142
167
  var asyncReturn = () => sleep(0);
143
168
  var asyncTimeout = async (promise, timeout2, err) => {
169
+ if (typeof promise === "function") {
170
+ throw new Error("First argument must be a promise.");
171
+ }
144
172
  let timeoutId;
145
173
  const throwable = err === void 0 || typeof err === "string" ? new TimeoutError(timeout2, err) : err;
146
174
  const timeoutPromise = new Promise((resolve, reject) => {
@@ -149,9 +177,8 @@ var asyncTimeout = async (promise, timeout2, err) => {
149
177
  }, timeout2);
150
178
  unrefTimeout(timeoutId);
151
179
  });
152
- const conditionTimeout = typeof promise === "function" ? promiseFromCallback(promise) : promise;
153
180
  return await Promise.race([
154
- conditionTimeout,
181
+ promise,
155
182
  timeoutPromise
156
183
  ]).finally(() => {
157
184
  clearTimeout(timeoutId);
@@ -191,10 +218,6 @@ import { Context } from "@dxos/context";
191
218
  var __dxlog_file = "/__w/dxos/dxos/packages/common/async/src/events.ts";
192
219
  var DO_NOT_ERROR_ON_ASYNC_CALLBACK = true;
193
220
  var Event = class _Event {
194
- constructor() {
195
- this._listeners = /* @__PURE__ */ new Set();
196
- this._effects = /* @__PURE__ */ new Set();
197
- }
198
221
  /**
199
222
  * Wrap objects that have on/off style event emitters.
200
223
  */
@@ -207,6 +230,8 @@ var Event = class _Event {
207
230
  });
208
231
  return event;
209
232
  }
233
+ _listeners = /* @__PURE__ */ new Set();
234
+ _effects = /* @__PURE__ */ new Set();
210
235
  /**
211
236
  * Emit an event.
212
237
  * In most cases should only be called by the class or entity containing the event.
@@ -450,11 +475,15 @@ var Event = class _Event {
450
475
  }
451
476
  };
452
477
  var EventListener = class {
478
+ ctx;
479
+ once;
480
+ weak;
481
+ callback;
482
+ _clearDispose = void 0;
453
483
  constructor(event, listener, ctx, once, weak) {
454
484
  this.ctx = ctx;
455
485
  this.once = once;
456
486
  this.weak = weak;
457
- this._clearDispose = void 0;
458
487
  this._clearDispose = ctx.onDispose(() => {
459
488
  event._removeListener(this);
460
489
  });
@@ -518,11 +547,9 @@ var weakListeners = () => {
518
547
  import "@dxos/util";
519
548
  import { warnAfterTimeout } from "@dxos/debug";
520
549
  var Mutex = class {
521
- constructor() {
522
- this._queue = Promise.resolve();
523
- this._queueLength = 0;
524
- this._tag = null;
525
- }
550
+ _queue = Promise.resolve();
551
+ _queueLength = 0;
552
+ _tag = null;
526
553
  get tag() {
527
554
  return this._tag;
528
555
  }
@@ -568,6 +595,7 @@ var Mutex = class {
568
595
  }
569
596
  };
570
597
  var MutexGuard = class {
598
+ _release;
571
599
  constructor(_release) {
572
600
  this._release = _release;
573
601
  }
@@ -581,7 +609,7 @@ var MutexGuard = class {
581
609
  this.release();
582
610
  }
583
611
  };
584
- var classMutexSymbol = Symbol("class-mutex");
612
+ var classMutexSymbol = /* @__PURE__ */ Symbol("class-mutex");
585
613
  var FORCE_DISABLE_WARNING = false;
586
614
  var enableWarning = !FORCE_DISABLE_WARNING && globalThis.mochaExecutor;
587
615
  var synchronized = (target, propertyName, descriptor) => {
@@ -628,18 +656,22 @@ var trigger = (timeout2) => {
628
656
  resolver
629
657
  ];
630
658
  };
631
- var TriggerState = /* @__PURE__ */ function(TriggerState2) {
659
+ var TriggerState = /* @__PURE__ */ (function(TriggerState2) {
632
660
  TriggerState2["WAITING"] = "WAITING";
633
661
  TriggerState2["RESOLVED"] = "RESOLVED";
634
662
  TriggerState2["REJECTED"] = "REJECTED";
635
663
  return TriggerState2;
636
- }({});
664
+ })({});
637
665
  var Trigger = class {
666
+ _options;
667
+ _promise;
668
+ _resolve;
669
+ _reject;
670
+ _state = "WAITING";
638
671
  constructor(_options = {
639
672
  autoReset: false
640
673
  }) {
641
674
  this._options = _options;
642
- this._state = "WAITING";
643
675
  this.reset();
644
676
  }
645
677
  get state() {
@@ -748,20 +780,12 @@ var latch = ({ count = 1, timeout: timeout2 } = {}) => {
748
780
 
749
781
  // src/observable.ts
750
782
  var MulticastObservable = class _MulticastObservable extends Observable {
783
+ _value;
784
+ _observers = /* @__PURE__ */ new Set();
785
+ _observable;
786
+ _completed = new Trigger();
751
787
  constructor(subscriber, _value) {
752
- super((observer) => this._subscribe(observer)), this._value = _value, this._observers = /* @__PURE__ */ new Set(), this._completed = new Trigger(), this._handlers = {
753
- next: (value) => {
754
- this._value = value;
755
- this._observers.forEach((observer) => observer.next?.(value));
756
- },
757
- error: (err) => {
758
- this._observers.forEach((observer) => observer.error?.(err));
759
- },
760
- complete: () => {
761
- this._completed.wake();
762
- this._observers.forEach((observer) => observer.complete?.());
763
- }
764
- };
788
+ super((observer) => this._subscribe(observer)), this._value = _value;
765
789
  this._observable = typeof subscriber === "function" ? new Observable(subscriber) : subscriber;
766
790
  this._observable.subscribe(this._handlers);
767
791
  }
@@ -845,18 +869,30 @@ var MulticastObservable = class _MulticastObservable extends Observable {
845
869
  this._observers.delete(observer);
846
870
  };
847
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
+ };
848
885
  };
849
886
  var EMPTY_OBSERVABLE = MulticastObservable.of(null);
850
887
 
851
888
  // src/observable-value.ts
852
889
  import { createSetDispatch } from "@dxos/util";
853
890
  var ObservableProvider = class {
854
- constructor() {
855
- this._handlers = /* @__PURE__ */ new Set();
856
- this._proxy = createSetDispatch({
857
- handlers: this._handlers
858
- });
859
- }
891
+ _handlers = /* @__PURE__ */ new Set();
892
+ _proxy = createSetDispatch({
893
+ handlers: this._handlers
894
+ });
895
+ _value;
860
896
  /**
861
897
  * Proxy used to dispatch callbacks to each subscription.
862
898
  */
@@ -877,8 +913,10 @@ var ObservableProvider = class {
877
913
  }
878
914
  };
879
915
  var CancellableObservableProvider = class extends ObservableProvider {
916
+ _handleCancel;
917
+ _cancelled = false;
880
918
  constructor(_handleCancel) {
881
- super(), this._handleCancel = _handleCancel, this._cancelled = false;
919
+ super(), this._handleCancel = _handleCancel;
882
920
  }
883
921
  get cancelled() {
884
922
  return this._cancelled;
@@ -899,7 +937,7 @@ import { warnAfterTimeout as warnAfterTimeout2 } from "@dxos/debug";
899
937
  import { log as log2 } from "@dxos/log";
900
938
 
901
939
  // src/task-scheduling.ts
902
- import { ContextDisposedError as ContextDisposedError2 } from "@dxos/context";
940
+ import { Context as Context2, ContextDisposedError as ContextDisposedError2 } from "@dxos/context";
903
941
  import { StackTrace as StackTrace2 } from "@dxos/debug";
904
942
 
905
943
  // src/track-leaks.ts
@@ -908,7 +946,7 @@ import { log } from "@dxos/log";
908
946
  var __dxlog_file3 = "/__w/dxos/dxos/packages/common/async/src/track-leaks.ts";
909
947
  var enabled = typeof process !== "undefined" && !!process.env.DX_TRACK_LEAKS;
910
948
  var openResources = /* @__PURE__ */ new Set();
911
- var handleSymbol = Symbol("checkLeaksHandle");
949
+ var handleSymbol = /* @__PURE__ */ Symbol("checkLeaksHandle");
912
950
  var trackResource = (resourceProvider) => {
913
951
  if (!enabled) {
914
952
  return () => {
@@ -987,13 +1025,16 @@ if (enabled) {
987
1025
  }
988
1026
 
989
1027
  // src/task-scheduling.ts
1028
+ var __dxlog_file4 = "/__w/dxos/dxos/packages/common/async/src/task-scheduling.ts";
990
1029
  var DeferredTask = class {
1030
+ _ctx;
1031
+ _callback;
1032
+ _scheduled = false;
1033
+ _currentTask = null;
1034
+ _nextTask = new Trigger();
991
1035
  constructor(_ctx, _callback) {
992
1036
  this._ctx = _ctx;
993
1037
  this._callback = _callback;
994
- this._scheduled = false;
995
- this._currentTask = null;
996
- this._nextTask = new Trigger();
997
1038
  }
998
1039
  get scheduled() {
999
1040
  return this._scheduled;
@@ -1034,6 +1075,82 @@ var DeferredTask = class {
1034
1075
  await this._currentTask;
1035
1076
  }
1036
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
+ };
1037
1154
  var runInContext = (ctx, fn) => {
1038
1155
  try {
1039
1156
  fn();
@@ -1119,15 +1236,19 @@ function _ts_decorate(decorators, target, key, desc) {
1119
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;
1120
1237
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1121
1238
  }
1122
- 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";
1123
1240
  var INIT_RESTART_DELAY = 100;
1124
1241
  var DEFAULT_MAX_RESTART_DELAY = 5e3;
1125
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;
1126
1250
  constructor({ start, stop, onRestart, maxRestartDelay = DEFAULT_MAX_RESTART_DELAY }) {
1127
1251
  super();
1128
- this._currentState = void 0;
1129
- this._restartTask = void 0;
1130
- this._restartAfter = 0;
1131
1252
  this._start = start;
1132
1253
  this._stop = stop;
1133
1254
  this._onRestart = onRestart;
@@ -1144,7 +1265,7 @@ var PersistentLifecycle = class extends Resource {
1144
1265
  log2.warn("Restart failed", {
1145
1266
  err
1146
1267
  }, {
1147
- F: __dxlog_file4,
1268
+ F: __dxlog_file5,
1148
1269
  L: 72,
1149
1270
  S: this,
1150
1271
  C: (f, a) => f(...a)
@@ -1156,7 +1277,7 @@ var PersistentLifecycle = class extends Resource {
1156
1277
  log2.warn("Start failed", {
1157
1278
  err
1158
1279
  }, {
1159
- F: __dxlog_file4,
1280
+ F: __dxlog_file5,
1160
1281
  L: 78,
1161
1282
  S: this,
1162
1283
  C: (f, a) => f(...a)
@@ -1174,7 +1295,7 @@ var PersistentLifecycle = class extends Resource {
1174
1295
  log2(`restarting in ${this._restartAfter}ms`, {
1175
1296
  state: this._lifecycleState
1176
1297
  }, {
1177
- F: __dxlog_file4,
1298
+ F: __dxlog_file5,
1178
1299
  L: 91,
1179
1300
  S: this,
1180
1301
  C: (f, a) => f(...a)
@@ -1197,7 +1318,7 @@ var PersistentLifecycle = class extends Resource {
1197
1318
  await this._stop(this._currentState);
1198
1319
  } catch (err) {
1199
1320
  log2.catch(err, void 0, {
1200
- F: __dxlog_file4,
1321
+ F: __dxlog_file5,
1201
1322
  L: 113,
1202
1323
  S: this,
1203
1324
  C: (f, a) => f(...a)
@@ -1225,7 +1346,7 @@ _ts_decorate([
1225
1346
 
1226
1347
  // src/push-iterable.ts
1227
1348
  import { invariant as invariant2 } from "@dxos/invariant";
1228
- 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";
1229
1350
  var makePushIterable = () => {
1230
1351
  const buf = [];
1231
1352
  const trigger2 = new Trigger({
@@ -1240,7 +1361,7 @@ var makePushIterable = () => {
1240
1361
  }
1241
1362
  const item = buf.shift();
1242
1363
  invariant2(item, void 0, {
1243
- F: __dxlog_file5,
1364
+ F: __dxlog_file6,
1244
1365
  L: 42,
1245
1366
  S: this,
1246
1367
  A: [
@@ -1334,11 +1455,6 @@ var streamToArray = (stream) => {
1334
1455
  // src/test-stream.ts
1335
1456
  import { Duplex } from "@dxos/node-std/stream";
1336
1457
  var TestStream = class extends Duplex {
1337
- constructor() {
1338
- super(...arguments);
1339
- this._received = Buffer.alloc(0);
1340
- this._onWrite = new Event();
1341
- }
1342
1458
  static async assertConnectivity(stream1, stream2, { timeout: timeout2 = 200 } = {}) {
1343
1459
  stream1.push("ping");
1344
1460
  stream2.push("pong");
@@ -1351,6 +1467,8 @@ var TestStream = class extends Duplex {
1351
1467
  })
1352
1468
  ]);
1353
1469
  }
1470
+ _received = Buffer.alloc(0);
1471
+ _onWrite = new Event();
1354
1472
  _write(chunk, encoding, callback) {
1355
1473
  this._received = Buffer.concat([
1356
1474
  this._received,
@@ -1428,10 +1546,12 @@ var untilError = (cb) => {
1428
1546
 
1429
1547
  // src/timer.ts
1430
1548
  var Timer = class {
1549
+ _callback;
1550
+ _state = new Event();
1551
+ _timer;
1552
+ _count = 0;
1431
1553
  constructor(_callback) {
1432
1554
  this._callback = _callback;
1433
- this._state = new Event();
1434
- this._count = 0;
1435
1555
  }
1436
1556
  get state() {
1437
1557
  return this._state;
@@ -1477,13 +1597,20 @@ var Timer = class {
1477
1597
  // src/update-scheduler.ts
1478
1598
  var TIME_PERIOD = 1e3;
1479
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;
1480
1610
  constructor(_ctx, _callback, _params = {}) {
1481
1611
  this._ctx = _ctx;
1482
1612
  this._callback = _callback;
1483
1613
  this._params = _params;
1484
- this._promise = null;
1485
- this._scheduled = false;
1486
- this._lastUpdateTime = -TIME_PERIOD;
1487
1614
  _ctx.onDispose(async () => {
1488
1615
  await this._promise;
1489
1616
  });
@@ -1496,13 +1623,13 @@ var UpdateScheduler = class {
1496
1623
  await this._promise;
1497
1624
  if (this._params.maxFrequency) {
1498
1625
  const now = performance.now();
1499
- const delay = this._lastUpdateTime + TIME_PERIOD / this._params.maxFrequency - now;
1500
- if (delay > 0) {
1626
+ const delay2 = this._lastUpdateTime + TIME_PERIOD / this._params.maxFrequency - now;
1627
+ if (delay2 > 0) {
1501
1628
  await new Promise((resolve) => {
1502
1629
  const timeoutId = setTimeout(() => {
1503
1630
  clearContext();
1504
1631
  resolve();
1505
- }, delay);
1632
+ }, delay2);
1506
1633
  const clearContext = this._ctx.onDispose(() => {
1507
1634
  clearTimeout(timeoutId);
1508
1635
  resolve();
@@ -1546,6 +1673,7 @@ var UpdateScheduler = class {
1546
1673
  }
1547
1674
  };
1548
1675
  export {
1676
+ AsyncTask,
1549
1677
  CancellableObservableProvider,
1550
1678
  DeferredTask,
1551
1679
  Event,
@@ -1572,6 +1700,7 @@ export {
1572
1700
  combine,
1573
1701
  debounce,
1574
1702
  debounceAndThrottle,
1703
+ delay,
1575
1704
  dumpLeaks,
1576
1705
  interval,
1577
1706
  latch,