@dxos/async 0.8.4-main.b97322e → 0.8.4-main.bc674ce
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.
- package/dist/lib/browser/index.mjs +186 -64
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +186 -64
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/cleanup.d.ts +1 -0
- package/dist/types/src/cleanup.d.ts.map +1 -1
- package/dist/types/src/debounce.d.ts +15 -0
- package/dist/types/src/debounce.d.ts.map +1 -1
- package/dist/types/src/persistent-lifecycle.d.ts +2 -2
- package/dist/types/src/persistent-lifecycle.d.ts.map +1 -1
- package/dist/types/src/task-scheduling.d.ts +28 -0
- package/dist/types/src/task-scheduling.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +13 -9
- package/src/cleanup.ts +1 -0
- package/src/debounce.ts +52 -4
- package/src/event-emitter.test.ts +1 -0
- package/src/persistent-lifecycle.test.ts +1 -1
- package/src/persistent-lifecycle.ts +2 -2
- package/src/task-scheduling.ts +94 -1
- package/src/testing.test.ts +1 -1
|
@@ -38,9 +38,7 @@ var addEventListener = (target, type, listener, options) => {
|
|
|
38
38
|
return () => target.removeEventListener(type, listener, options);
|
|
39
39
|
};
|
|
40
40
|
var SubscriptionList = class {
|
|
41
|
-
|
|
42
|
-
this._cleanups = [];
|
|
43
|
-
}
|
|
41
|
+
_cleanups = [];
|
|
44
42
|
add(cb) {
|
|
45
43
|
this._cleanups.push(cb);
|
|
46
44
|
return this;
|
|
@@ -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
|
|
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),
|
|
87
|
+
t = setTimeout(() => cb(...args), delay2);
|
|
73
88
|
};
|
|
74
89
|
};
|
|
75
|
-
var throttle = (cb,
|
|
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 >=
|
|
94
|
+
if (now - lastCall >= delay2) {
|
|
80
95
|
cb(...args);
|
|
81
96
|
lastCall = now;
|
|
82
97
|
}
|
|
83
98
|
};
|
|
84
99
|
};
|
|
85
|
-
var debounceAndThrottle = (cb,
|
|
86
|
-
|
|
87
|
-
|
|
100
|
+
var debounceAndThrottle = (cb, delay2 = 100) => {
|
|
101
|
+
let timeout2;
|
|
102
|
+
let lastCall = 0;
|
|
88
103
|
return (...args) => {
|
|
89
|
-
|
|
90
|
-
|
|
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
|
|
|
@@ -191,10 +216,6 @@ import { Context } from "@dxos/context";
|
|
|
191
216
|
var __dxlog_file = "/__w/dxos/dxos/packages/common/async/src/events.ts";
|
|
192
217
|
var DO_NOT_ERROR_ON_ASYNC_CALLBACK = true;
|
|
193
218
|
var Event = class _Event {
|
|
194
|
-
constructor() {
|
|
195
|
-
this._listeners = /* @__PURE__ */ new Set();
|
|
196
|
-
this._effects = /* @__PURE__ */ new Set();
|
|
197
|
-
}
|
|
198
219
|
/**
|
|
199
220
|
* Wrap objects that have on/off style event emitters.
|
|
200
221
|
*/
|
|
@@ -207,6 +228,8 @@ var Event = class _Event {
|
|
|
207
228
|
});
|
|
208
229
|
return event;
|
|
209
230
|
}
|
|
231
|
+
_listeners = /* @__PURE__ */ new Set();
|
|
232
|
+
_effects = /* @__PURE__ */ new Set();
|
|
210
233
|
/**
|
|
211
234
|
* Emit an event.
|
|
212
235
|
* In most cases should only be called by the class or entity containing the event.
|
|
@@ -450,11 +473,15 @@ var Event = class _Event {
|
|
|
450
473
|
}
|
|
451
474
|
};
|
|
452
475
|
var EventListener = class {
|
|
476
|
+
ctx;
|
|
477
|
+
once;
|
|
478
|
+
weak;
|
|
479
|
+
callback;
|
|
480
|
+
_clearDispose = void 0;
|
|
453
481
|
constructor(event, listener, ctx, once, weak) {
|
|
454
482
|
this.ctx = ctx;
|
|
455
483
|
this.once = once;
|
|
456
484
|
this.weak = weak;
|
|
457
|
-
this._clearDispose = void 0;
|
|
458
485
|
this._clearDispose = ctx.onDispose(() => {
|
|
459
486
|
event._removeListener(this);
|
|
460
487
|
});
|
|
@@ -518,11 +545,9 @@ var weakListeners = () => {
|
|
|
518
545
|
import "@dxos/util";
|
|
519
546
|
import { warnAfterTimeout } from "@dxos/debug";
|
|
520
547
|
var Mutex = class {
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
this._tag = null;
|
|
525
|
-
}
|
|
548
|
+
_queue = Promise.resolve();
|
|
549
|
+
_queueLength = 0;
|
|
550
|
+
_tag = null;
|
|
526
551
|
get tag() {
|
|
527
552
|
return this._tag;
|
|
528
553
|
}
|
|
@@ -568,6 +593,7 @@ var Mutex = class {
|
|
|
568
593
|
}
|
|
569
594
|
};
|
|
570
595
|
var MutexGuard = class {
|
|
596
|
+
_release;
|
|
571
597
|
constructor(_release) {
|
|
572
598
|
this._release = _release;
|
|
573
599
|
}
|
|
@@ -628,18 +654,22 @@ var trigger = (timeout2) => {
|
|
|
628
654
|
resolver
|
|
629
655
|
];
|
|
630
656
|
};
|
|
631
|
-
var TriggerState = /* @__PURE__ */ function(TriggerState2) {
|
|
657
|
+
var TriggerState = /* @__PURE__ */ (function(TriggerState2) {
|
|
632
658
|
TriggerState2["WAITING"] = "WAITING";
|
|
633
659
|
TriggerState2["RESOLVED"] = "RESOLVED";
|
|
634
660
|
TriggerState2["REJECTED"] = "REJECTED";
|
|
635
661
|
return TriggerState2;
|
|
636
|
-
}({});
|
|
662
|
+
})({});
|
|
637
663
|
var Trigger = class {
|
|
664
|
+
_options;
|
|
665
|
+
_promise;
|
|
666
|
+
_resolve;
|
|
667
|
+
_reject;
|
|
668
|
+
_state = "WAITING";
|
|
638
669
|
constructor(_options = {
|
|
639
670
|
autoReset: false
|
|
640
671
|
}) {
|
|
641
672
|
this._options = _options;
|
|
642
|
-
this._state = "WAITING";
|
|
643
673
|
this.reset();
|
|
644
674
|
}
|
|
645
675
|
get state() {
|
|
@@ -748,20 +778,12 @@ var latch = ({ count = 1, timeout: timeout2 } = {}) => {
|
|
|
748
778
|
|
|
749
779
|
// src/observable.ts
|
|
750
780
|
var MulticastObservable = class _MulticastObservable extends Observable {
|
|
781
|
+
_value;
|
|
782
|
+
_observers = /* @__PURE__ */ new Set();
|
|
783
|
+
_observable;
|
|
784
|
+
_completed = new Trigger();
|
|
751
785
|
constructor(subscriber, _value) {
|
|
752
|
-
super((observer) => this._subscribe(observer)), this._value = _value
|
|
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
|
-
};
|
|
786
|
+
super((observer) => this._subscribe(observer)), this._value = _value;
|
|
765
787
|
this._observable = typeof subscriber === "function" ? new Observable(subscriber) : subscriber;
|
|
766
788
|
this._observable.subscribe(this._handlers);
|
|
767
789
|
}
|
|
@@ -845,18 +867,30 @@ var MulticastObservable = class _MulticastObservable extends Observable {
|
|
|
845
867
|
this._observers.delete(observer);
|
|
846
868
|
};
|
|
847
869
|
}
|
|
870
|
+
_handlers = {
|
|
871
|
+
next: (value) => {
|
|
872
|
+
this._value = value;
|
|
873
|
+
this._observers.forEach((observer) => observer.next?.(value));
|
|
874
|
+
},
|
|
875
|
+
error: (err) => {
|
|
876
|
+
this._observers.forEach((observer) => observer.error?.(err));
|
|
877
|
+
},
|
|
878
|
+
complete: () => {
|
|
879
|
+
this._completed.wake();
|
|
880
|
+
this._observers.forEach((observer) => observer.complete?.());
|
|
881
|
+
}
|
|
882
|
+
};
|
|
848
883
|
};
|
|
849
884
|
var EMPTY_OBSERVABLE = MulticastObservable.of(null);
|
|
850
885
|
|
|
851
886
|
// src/observable-value.ts
|
|
852
887
|
import { createSetDispatch } from "@dxos/util";
|
|
853
888
|
var ObservableProvider = class {
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
this.
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
}
|
|
889
|
+
_handlers = /* @__PURE__ */ new Set();
|
|
890
|
+
_proxy = createSetDispatch({
|
|
891
|
+
handlers: this._handlers
|
|
892
|
+
});
|
|
893
|
+
_value;
|
|
860
894
|
/**
|
|
861
895
|
* Proxy used to dispatch callbacks to each subscription.
|
|
862
896
|
*/
|
|
@@ -877,8 +911,10 @@ var ObservableProvider = class {
|
|
|
877
911
|
}
|
|
878
912
|
};
|
|
879
913
|
var CancellableObservableProvider = class extends ObservableProvider {
|
|
914
|
+
_handleCancel;
|
|
915
|
+
_cancelled = false;
|
|
880
916
|
constructor(_handleCancel) {
|
|
881
|
-
super(), this._handleCancel = _handleCancel
|
|
917
|
+
super(), this._handleCancel = _handleCancel;
|
|
882
918
|
}
|
|
883
919
|
get cancelled() {
|
|
884
920
|
return this._cancelled;
|
|
@@ -988,12 +1024,14 @@ if (enabled) {
|
|
|
988
1024
|
|
|
989
1025
|
// src/task-scheduling.ts
|
|
990
1026
|
var DeferredTask = class {
|
|
1027
|
+
_ctx;
|
|
1028
|
+
_callback;
|
|
1029
|
+
_scheduled = false;
|
|
1030
|
+
_currentTask = null;
|
|
1031
|
+
_nextTask = new Trigger();
|
|
991
1032
|
constructor(_ctx, _callback) {
|
|
992
1033
|
this._ctx = _ctx;
|
|
993
1034
|
this._callback = _callback;
|
|
994
|
-
this._scheduled = false;
|
|
995
|
-
this._currentTask = null;
|
|
996
|
-
this._nextTask = new Trigger();
|
|
997
1035
|
}
|
|
998
1036
|
get scheduled() {
|
|
999
1037
|
return this._scheduled;
|
|
@@ -1034,6 +1072,78 @@ var DeferredTask = class {
|
|
|
1034
1072
|
await this._currentTask;
|
|
1035
1073
|
}
|
|
1036
1074
|
};
|
|
1075
|
+
var AsyncTask = class {
|
|
1076
|
+
#callback;
|
|
1077
|
+
#ctx = void 0;
|
|
1078
|
+
#scheduled = false;
|
|
1079
|
+
#currentTask = null;
|
|
1080
|
+
#nextTask = new Trigger();
|
|
1081
|
+
constructor(callback) {
|
|
1082
|
+
this.#callback = callback;
|
|
1083
|
+
}
|
|
1084
|
+
get scheduled() {
|
|
1085
|
+
return this.#scheduled;
|
|
1086
|
+
}
|
|
1087
|
+
/**
|
|
1088
|
+
* Context of the resource that owns the task.
|
|
1089
|
+
* When the context is disposed, the task is cancelled and cannot be scheduled again.
|
|
1090
|
+
*/
|
|
1091
|
+
// TODO(dmaretskyi): We don't really need to pass ctx in here, since close will also signal dispose.
|
|
1092
|
+
open(ctx) {
|
|
1093
|
+
this.#ctx = ctx;
|
|
1094
|
+
}
|
|
1095
|
+
/**
|
|
1096
|
+
* Closes the task and waits for it to finish if it is running.
|
|
1097
|
+
*/
|
|
1098
|
+
async close() {
|
|
1099
|
+
this.#ctx = void 0;
|
|
1100
|
+
await this.join();
|
|
1101
|
+
}
|
|
1102
|
+
[Symbol.asyncDispose]() {
|
|
1103
|
+
return this.close();
|
|
1104
|
+
}
|
|
1105
|
+
/**
|
|
1106
|
+
* Schedule the task to run asynchronously.
|
|
1107
|
+
*/
|
|
1108
|
+
schedule() {
|
|
1109
|
+
if (!this.#ctx || this.#ctx.disposed) {
|
|
1110
|
+
throw new Error("AsyncTask not open");
|
|
1111
|
+
}
|
|
1112
|
+
if (this.#scheduled) {
|
|
1113
|
+
return;
|
|
1114
|
+
}
|
|
1115
|
+
scheduleTask(this.#ctx, async () => {
|
|
1116
|
+
await this.#currentTask;
|
|
1117
|
+
if (!this.#ctx || this.#ctx.disposed) {
|
|
1118
|
+
return;
|
|
1119
|
+
}
|
|
1120
|
+
this.#scheduled = false;
|
|
1121
|
+
const completionTrigger = this.#nextTask;
|
|
1122
|
+
this.#nextTask = new Trigger();
|
|
1123
|
+
this.#currentTask = runInContextAsync(this.#ctx, () => this.#callback()).then(() => {
|
|
1124
|
+
completionTrigger.wake();
|
|
1125
|
+
});
|
|
1126
|
+
});
|
|
1127
|
+
this.#scheduled = true;
|
|
1128
|
+
}
|
|
1129
|
+
/**
|
|
1130
|
+
* Schedule the task to run and wait for it to finish.
|
|
1131
|
+
*/
|
|
1132
|
+
async runBlocking() {
|
|
1133
|
+
if (this.#ctx?.disposed) {
|
|
1134
|
+
throw new ContextDisposedError2();
|
|
1135
|
+
}
|
|
1136
|
+
this.schedule();
|
|
1137
|
+
await this.#nextTask.wait();
|
|
1138
|
+
}
|
|
1139
|
+
/**
|
|
1140
|
+
* Waits for the current task to finish if it is running.
|
|
1141
|
+
* Does not schedule a new task.
|
|
1142
|
+
*/
|
|
1143
|
+
async join() {
|
|
1144
|
+
await this.#currentTask;
|
|
1145
|
+
}
|
|
1146
|
+
};
|
|
1037
1147
|
var runInContext = (ctx, fn) => {
|
|
1038
1148
|
try {
|
|
1039
1149
|
fn();
|
|
@@ -1123,11 +1233,15 @@ var __dxlog_file4 = "/__w/dxos/dxos/packages/common/async/src/persistent-lifecyc
|
|
|
1123
1233
|
var INIT_RESTART_DELAY = 100;
|
|
1124
1234
|
var DEFAULT_MAX_RESTART_DELAY = 5e3;
|
|
1125
1235
|
var PersistentLifecycle = class extends Resource {
|
|
1236
|
+
_start;
|
|
1237
|
+
_stop;
|
|
1238
|
+
_onRestart;
|
|
1239
|
+
_maxRestartDelay;
|
|
1240
|
+
_currentState = void 0;
|
|
1241
|
+
_restartTask = void 0;
|
|
1242
|
+
_restartAfter = 0;
|
|
1126
1243
|
constructor({ start, stop, onRestart, maxRestartDelay = DEFAULT_MAX_RESTART_DELAY }) {
|
|
1127
1244
|
super();
|
|
1128
|
-
this._currentState = void 0;
|
|
1129
|
-
this._restartTask = void 0;
|
|
1130
|
-
this._restartAfter = 0;
|
|
1131
1245
|
this._start = start;
|
|
1132
1246
|
this._stop = stop;
|
|
1133
1247
|
this._onRestart = onRestart;
|
|
@@ -1334,11 +1448,6 @@ var streamToArray = (stream) => {
|
|
|
1334
1448
|
// src/test-stream.ts
|
|
1335
1449
|
import { Duplex } from "@dxos/node-std/stream";
|
|
1336
1450
|
var TestStream = class extends Duplex {
|
|
1337
|
-
constructor() {
|
|
1338
|
-
super(...arguments);
|
|
1339
|
-
this._received = Buffer.alloc(0);
|
|
1340
|
-
this._onWrite = new Event();
|
|
1341
|
-
}
|
|
1342
1451
|
static async assertConnectivity(stream1, stream2, { timeout: timeout2 = 200 } = {}) {
|
|
1343
1452
|
stream1.push("ping");
|
|
1344
1453
|
stream2.push("pong");
|
|
@@ -1351,6 +1460,8 @@ var TestStream = class extends Duplex {
|
|
|
1351
1460
|
})
|
|
1352
1461
|
]);
|
|
1353
1462
|
}
|
|
1463
|
+
_received = Buffer.alloc(0);
|
|
1464
|
+
_onWrite = new Event();
|
|
1354
1465
|
_write(chunk, encoding, callback) {
|
|
1355
1466
|
this._received = Buffer.concat([
|
|
1356
1467
|
this._received,
|
|
@@ -1428,10 +1539,12 @@ var untilError = (cb) => {
|
|
|
1428
1539
|
|
|
1429
1540
|
// src/timer.ts
|
|
1430
1541
|
var Timer = class {
|
|
1542
|
+
_callback;
|
|
1543
|
+
_state = new Event();
|
|
1544
|
+
_timer;
|
|
1545
|
+
_count = 0;
|
|
1431
1546
|
constructor(_callback) {
|
|
1432
1547
|
this._callback = _callback;
|
|
1433
|
-
this._state = new Event();
|
|
1434
|
-
this._count = 0;
|
|
1435
1548
|
}
|
|
1436
1549
|
get state() {
|
|
1437
1550
|
return this._state;
|
|
@@ -1477,13 +1590,20 @@ var Timer = class {
|
|
|
1477
1590
|
// src/update-scheduler.ts
|
|
1478
1591
|
var TIME_PERIOD = 1e3;
|
|
1479
1592
|
var UpdateScheduler = class {
|
|
1593
|
+
_ctx;
|
|
1594
|
+
_callback;
|
|
1595
|
+
_params;
|
|
1596
|
+
/**
|
|
1597
|
+
* Promise that resolves when the callback is done.
|
|
1598
|
+
* Never rejects.
|
|
1599
|
+
*/
|
|
1600
|
+
_promise = null;
|
|
1601
|
+
_scheduled = false;
|
|
1602
|
+
_lastUpdateTime = -TIME_PERIOD;
|
|
1480
1603
|
constructor(_ctx, _callback, _params = {}) {
|
|
1481
1604
|
this._ctx = _ctx;
|
|
1482
1605
|
this._callback = _callback;
|
|
1483
1606
|
this._params = _params;
|
|
1484
|
-
this._promise = null;
|
|
1485
|
-
this._scheduled = false;
|
|
1486
|
-
this._lastUpdateTime = -TIME_PERIOD;
|
|
1487
1607
|
_ctx.onDispose(async () => {
|
|
1488
1608
|
await this._promise;
|
|
1489
1609
|
});
|
|
@@ -1496,13 +1616,13 @@ var UpdateScheduler = class {
|
|
|
1496
1616
|
await this._promise;
|
|
1497
1617
|
if (this._params.maxFrequency) {
|
|
1498
1618
|
const now = performance.now();
|
|
1499
|
-
const
|
|
1500
|
-
if (
|
|
1619
|
+
const delay2 = this._lastUpdateTime + TIME_PERIOD / this._params.maxFrequency - now;
|
|
1620
|
+
if (delay2 > 0) {
|
|
1501
1621
|
await new Promise((resolve) => {
|
|
1502
1622
|
const timeoutId = setTimeout(() => {
|
|
1503
1623
|
clearContext();
|
|
1504
1624
|
resolve();
|
|
1505
|
-
},
|
|
1625
|
+
}, delay2);
|
|
1506
1626
|
const clearContext = this._ctx.onDispose(() => {
|
|
1507
1627
|
clearTimeout(timeoutId);
|
|
1508
1628
|
resolve();
|
|
@@ -1546,6 +1666,7 @@ var UpdateScheduler = class {
|
|
|
1546
1666
|
}
|
|
1547
1667
|
};
|
|
1548
1668
|
export {
|
|
1669
|
+
AsyncTask,
|
|
1549
1670
|
CancellableObservableProvider,
|
|
1550
1671
|
DeferredTask,
|
|
1551
1672
|
Event,
|
|
@@ -1572,6 +1693,7 @@ export {
|
|
|
1572
1693
|
combine,
|
|
1573
1694
|
debounce,
|
|
1574
1695
|
debounceAndThrottle,
|
|
1696
|
+
delay,
|
|
1575
1697
|
dumpLeaks,
|
|
1576
1698
|
interval,
|
|
1577
1699
|
latch,
|