@dxos/async 0.8.4-main.fd6878d → 0.8.4-staging.ac66bdf99f

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) => {
@@ -39,8 +39,8 @@ var addEventListener = (target, type, listener, options) => {
39
39
  };
40
40
  var SubscriptionList = class {
41
41
  _cleanups = [];
42
- add(cb) {
43
- this._cleanups.push(cb);
42
+ add(...cb) {
43
+ this._cleanups.push(...cb);
44
44
  return this;
45
45
  }
46
46
  clear() {
@@ -64,29 +64,55 @@ var SubscriptionSet = class {
64
64
  };
65
65
 
66
66
  // src/debounce.ts
67
- 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) => {
68
84
  let t;
69
85
  return (...args) => {
70
86
  clearTimeout(t);
71
- t = setTimeout(() => cb(...args), delay);
87
+ t = setTimeout(() => cb(...args), delay2);
72
88
  };
73
89
  };
74
- var throttle = (cb, delay = 100) => {
90
+ var throttle = (cb, delay2 = 100) => {
75
91
  let lastCall = 0;
76
92
  return (...args) => {
77
93
  const now = Date.now();
78
- if (now - lastCall >= delay) {
94
+ if (now - lastCall >= delay2) {
79
95
  cb(...args);
80
96
  lastCall = now;
81
97
  }
82
98
  };
83
99
  };
84
- var debounceAndThrottle = (cb, delay = 100) => {
85
- const debounced = debounce(cb, delay);
86
- const throttled = throttle(cb, delay);
100
+ var debounceAndThrottle = (cb, delay2 = 100) => {
101
+ let timeout2;
102
+ let lastCall = 0;
87
103
  return (...args) => {
88
- debounced(...args);
89
- 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
+ }
90
116
  };
91
117
  };
92
118
 
@@ -140,6 +166,9 @@ var sleepWithContext = (ctx, ms) => {
140
166
  };
141
167
  var asyncReturn = () => sleep(0);
142
168
  var asyncTimeout = async (promise, timeout2, err) => {
169
+ if (typeof promise === "function") {
170
+ throw new Error("First argument must be a promise.");
171
+ }
143
172
  let timeoutId;
144
173
  const throwable = err === void 0 || typeof err === "string" ? new TimeoutError(timeout2, err) : err;
145
174
  const timeoutPromise = new Promise((resolve, reject) => {
@@ -148,9 +177,8 @@ var asyncTimeout = async (promise, timeout2, err) => {
148
177
  }, timeout2);
149
178
  unrefTimeout(timeoutId);
150
179
  });
151
- const conditionTimeout = typeof promise === "function" ? promiseFromCallback(promise) : promise;
152
180
  return await Promise.race([
153
- conditionTimeout,
181
+ promise,
154
182
  timeoutPromise
155
183
  ]).finally(() => {
156
184
  clearTimeout(timeoutId);
@@ -451,12 +479,11 @@ var EventListener = class {
451
479
  once;
452
480
  weak;
453
481
  callback;
454
- _clearDispose;
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
  });
@@ -582,7 +609,7 @@ var MutexGuard = class {
582
609
  this.release();
583
610
  }
584
611
  };
585
- var classMutexSymbol = Symbol("class-mutex");
612
+ var classMutexSymbol = /* @__PURE__ */ Symbol("class-mutex");
586
613
  var FORCE_DISABLE_WARNING = false;
587
614
  var enableWarning = !FORCE_DISABLE_WARNING && globalThis.mochaExecutor;
588
615
  var synchronized = (target, propertyName, descriptor) => {
@@ -629,23 +656,22 @@ var trigger = (timeout2) => {
629
656
  resolver
630
657
  ];
631
658
  };
632
- var TriggerState = /* @__PURE__ */ function(TriggerState2) {
659
+ var TriggerState = /* @__PURE__ */ (function(TriggerState2) {
633
660
  TriggerState2["WAITING"] = "WAITING";
634
661
  TriggerState2["RESOLVED"] = "RESOLVED";
635
662
  TriggerState2["REJECTED"] = "REJECTED";
636
663
  return TriggerState2;
637
- }({});
664
+ })({});
638
665
  var Trigger = class {
639
666
  _options;
640
667
  _promise;
641
668
  _resolve;
642
669
  _reject;
643
- _state;
670
+ _state = "WAITING";
644
671
  constructor(_options = {
645
672
  autoReset: false
646
673
  }) {
647
674
  this._options = _options;
648
- this._state = "WAITING";
649
675
  this.reset();
650
676
  }
651
677
  get state() {
@@ -755,23 +781,11 @@ var latch = ({ count = 1, timeout: timeout2 } = {}) => {
755
781
  // src/observable.ts
756
782
  var MulticastObservable = class _MulticastObservable extends Observable {
757
783
  _value;
758
- _observers;
784
+ _observers = /* @__PURE__ */ new Set();
759
785
  _observable;
760
- _completed;
786
+ _completed = new Trigger();
761
787
  constructor(subscriber, _value) {
762
- super((observer) => this._subscribe(observer)), this._value = _value, this._observers = /* @__PURE__ */ new Set(), this._completed = new Trigger(), this._handlers = {
763
- next: (value) => {
764
- this._value = value;
765
- this._observers.forEach((observer) => observer.next?.(value));
766
- },
767
- error: (err) => {
768
- this._observers.forEach((observer) => observer.error?.(err));
769
- },
770
- complete: () => {
771
- this._completed.wake();
772
- this._observers.forEach((observer) => observer.complete?.());
773
- }
774
- };
788
+ super((observer) => this._subscribe(observer)), this._value = _value;
775
789
  this._observable = typeof subscriber === "function" ? new Observable(subscriber) : subscriber;
776
790
  this._observable.subscribe(this._handlers);
777
791
  }
@@ -855,7 +869,19 @@ var MulticastObservable = class _MulticastObservable extends Observable {
855
869
  this._observers.delete(observer);
856
870
  };
857
871
  }
858
- _handlers;
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
+ };
859
885
  };
860
886
  var EMPTY_OBSERVABLE = MulticastObservable.of(null);
861
887
 
@@ -888,9 +914,9 @@ var ObservableProvider = class {
888
914
  };
889
915
  var CancellableObservableProvider = class extends ObservableProvider {
890
916
  _handleCancel;
891
- _cancelled;
917
+ _cancelled = false;
892
918
  constructor(_handleCancel) {
893
- super(), this._handleCancel = _handleCancel, this._cancelled = false;
919
+ super(), this._handleCancel = _handleCancel;
894
920
  }
895
921
  get cancelled() {
896
922
  return this._cancelled;
@@ -911,7 +937,7 @@ import { warnAfterTimeout as warnAfterTimeout2 } from "@dxos/debug";
911
937
  import { log as log2 } from "@dxos/log";
912
938
 
913
939
  // src/task-scheduling.ts
914
- import { ContextDisposedError as ContextDisposedError2 } from "@dxos/context";
940
+ import { Context as Context2, ContextDisposedError as ContextDisposedError2 } from "@dxos/context";
915
941
  import { StackTrace as StackTrace2 } from "@dxos/debug";
916
942
 
917
943
  // src/track-leaks.ts
@@ -920,7 +946,7 @@ import { log } from "@dxos/log";
920
946
  var __dxlog_file3 = "/__w/dxos/dxos/packages/common/async/src/track-leaks.ts";
921
947
  var enabled = typeof process !== "undefined" && !!process.env.DX_TRACK_LEAKS;
922
948
  var openResources = /* @__PURE__ */ new Set();
923
- var handleSymbol = Symbol("checkLeaksHandle");
949
+ var handleSymbol = /* @__PURE__ */ Symbol("checkLeaksHandle");
924
950
  var trackResource = (resourceProvider) => {
925
951
  if (!enabled) {
926
952
  return () => {
@@ -999,18 +1025,16 @@ if (enabled) {
999
1025
  }
1000
1026
 
1001
1027
  // src/task-scheduling.ts
1028
+ var __dxlog_file4 = "/__w/dxos/dxos/packages/common/async/src/task-scheduling.ts";
1002
1029
  var DeferredTask = class {
1003
1030
  _ctx;
1004
1031
  _callback;
1005
- _scheduled;
1006
- _currentTask;
1007
- _nextTask;
1032
+ _scheduled = false;
1033
+ _currentTask = null;
1034
+ _nextTask = new Trigger();
1008
1035
  constructor(_ctx, _callback) {
1009
1036
  this._ctx = _ctx;
1010
1037
  this._callback = _callback;
1011
- this._scheduled = false;
1012
- this._currentTask = null;
1013
- this._nextTask = new Trigger();
1014
1038
  }
1015
1039
  get scheduled() {
1016
1040
  return this._scheduled;
@@ -1051,6 +1075,82 @@ var DeferredTask = class {
1051
1075
  await this._currentTask;
1052
1076
  }
1053
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
+ };
1054
1154
  var runInContext = (ctx, fn) => {
1055
1155
  try {
1056
1156
  fn();
@@ -1136,7 +1236,7 @@ function _ts_decorate(decorators, target, key, desc) {
1136
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;
1137
1237
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1138
1238
  }
1139
- 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";
1140
1240
  var INIT_RESTART_DELAY = 100;
1141
1241
  var DEFAULT_MAX_RESTART_DELAY = 5e3;
1142
1242
  var PersistentLifecycle = class extends Resource {
@@ -1165,7 +1265,7 @@ var PersistentLifecycle = class extends Resource {
1165
1265
  log2.warn("Restart failed", {
1166
1266
  err
1167
1267
  }, {
1168
- F: __dxlog_file4,
1268
+ F: __dxlog_file5,
1169
1269
  L: 72,
1170
1270
  S: this,
1171
1271
  C: (f, a) => f(...a)
@@ -1177,7 +1277,7 @@ var PersistentLifecycle = class extends Resource {
1177
1277
  log2.warn("Start failed", {
1178
1278
  err
1179
1279
  }, {
1180
- F: __dxlog_file4,
1280
+ F: __dxlog_file5,
1181
1281
  L: 78,
1182
1282
  S: this,
1183
1283
  C: (f, a) => f(...a)
@@ -1195,7 +1295,7 @@ var PersistentLifecycle = class extends Resource {
1195
1295
  log2(`restarting in ${this._restartAfter}ms`, {
1196
1296
  state: this._lifecycleState
1197
1297
  }, {
1198
- F: __dxlog_file4,
1298
+ F: __dxlog_file5,
1199
1299
  L: 91,
1200
1300
  S: this,
1201
1301
  C: (f, a) => f(...a)
@@ -1218,7 +1318,7 @@ var PersistentLifecycle = class extends Resource {
1218
1318
  await this._stop(this._currentState);
1219
1319
  } catch (err) {
1220
1320
  log2.catch(err, void 0, {
1221
- F: __dxlog_file4,
1321
+ F: __dxlog_file5,
1222
1322
  L: 113,
1223
1323
  S: this,
1224
1324
  C: (f, a) => f(...a)
@@ -1246,7 +1346,7 @@ _ts_decorate([
1246
1346
 
1247
1347
  // src/push-iterable.ts
1248
1348
  import { invariant as invariant2 } from "@dxos/invariant";
1249
- 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";
1250
1350
  var makePushIterable = () => {
1251
1351
  const buf = [];
1252
1352
  const trigger2 = new Trigger({
@@ -1261,7 +1361,7 @@ var makePushIterable = () => {
1261
1361
  }
1262
1362
  const item = buf.shift();
1263
1363
  invariant2(item, void 0, {
1264
- F: __dxlog_file5,
1364
+ F: __dxlog_file6,
1265
1365
  L: 42,
1266
1366
  S: this,
1267
1367
  A: [
@@ -1447,13 +1547,11 @@ var untilError = (cb) => {
1447
1547
  // src/timer.ts
1448
1548
  var Timer = class {
1449
1549
  _callback;
1450
- _state;
1550
+ _state = new Event();
1451
1551
  _timer;
1452
- _count;
1552
+ _count = 0;
1453
1553
  constructor(_callback) {
1454
1554
  this._callback = _callback;
1455
- this._state = new Event();
1456
- this._count = 0;
1457
1555
  }
1458
1556
  get state() {
1459
1557
  return this._state;
@@ -1506,16 +1604,13 @@ var UpdateScheduler = class {
1506
1604
  * Promise that resolves when the callback is done.
1507
1605
  * Never rejects.
1508
1606
  */
1509
- _promise;
1510
- _scheduled;
1511
- _lastUpdateTime;
1607
+ _promise = null;
1608
+ _scheduled = false;
1609
+ _lastUpdateTime = -TIME_PERIOD;
1512
1610
  constructor(_ctx, _callback, _params = {}) {
1513
1611
  this._ctx = _ctx;
1514
1612
  this._callback = _callback;
1515
1613
  this._params = _params;
1516
- this._promise = null;
1517
- this._scheduled = false;
1518
- this._lastUpdateTime = -TIME_PERIOD;
1519
1614
  _ctx.onDispose(async () => {
1520
1615
  await this._promise;
1521
1616
  });
@@ -1528,13 +1623,13 @@ var UpdateScheduler = class {
1528
1623
  await this._promise;
1529
1624
  if (this._params.maxFrequency) {
1530
1625
  const now = performance.now();
1531
- const delay = this._lastUpdateTime + TIME_PERIOD / this._params.maxFrequency - now;
1532
- if (delay > 0) {
1626
+ const delay2 = this._lastUpdateTime + TIME_PERIOD / this._params.maxFrequency - now;
1627
+ if (delay2 > 0) {
1533
1628
  await new Promise((resolve) => {
1534
1629
  const timeoutId = setTimeout(() => {
1535
1630
  clearContext();
1536
1631
  resolve();
1537
- }, delay);
1632
+ }, delay2);
1538
1633
  const clearContext = this._ctx.onDispose(() => {
1539
1634
  clearTimeout(timeoutId);
1540
1635
  resolve();
@@ -1578,6 +1673,7 @@ var UpdateScheduler = class {
1578
1673
  }
1579
1674
  };
1580
1675
  export {
1676
+ AsyncTask,
1581
1677
  CancellableObservableProvider,
1582
1678
  DeferredTask,
1583
1679
  Event,
@@ -1604,6 +1700,7 @@ export {
1604
1700
  combine,
1605
1701
  debounce,
1606
1702
  debounceAndThrottle,
1703
+ delay,
1607
1704
  dumpLeaks,
1608
1705
  interval,
1609
1706
  latch,