@dxos/async 0.7.4 → 0.7.5-labs.071a3e2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"task-scheduling.d.ts","sourceRoot":"","sources":["../../../src/task-scheduling.ts"],"names":[],"mappings":"AAIA,OAAO,EAAwB,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AAEnE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAK/C,MAAM,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC;AAEvC;;;;GAIG;AAGH,qBAAa,YAAY;IAMrB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAN5B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,YAAY,CAA8B;IAClD,OAAO,CAAC,SAAS,CAAiB;gBAGf,IAAI,EAAE,OAAO,EACb,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC;IAGjD;;OAEG;IACH,QAAQ;IAuBR;;OAEG;IACG,WAAW;IASjB;;;OAGG;IACG,IAAI;CAGX;AAED,eAAO,MAAM,YAAY,QAAS,OAAO,MAAM,MAAM,IAAI,SAMxD,CAAC;AAEF,eAAO,MAAM,iBAAiB,QAAe,OAAO,MAAM,MAAM,YAAY,CAAC,IAAI,CAAC,kBAMjF,CAAC;AAEF,eAAO,MAAM,iBAAiB,QAAS,OAAO,MAAM,MAAM,YAAY,CAAC,IAAI,CAAC,SAO3E,CAAC;AAEF,eAAO,MAAM,YAAY,QAAS,OAAO,MAAM,MAAM,YAAY,CAAC,IAAI,CAAC,YAAY,MAAM,SAgBxF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,QAAS,OAAO,QAAQ,MAAM,OAAO,CAAC,IAAI,CAAC,YAAY,MAAM,SAqB7F,CAAC;AAEF,eAAO,MAAM,sCAAsC,QAC5C,OAAO,QACN,MAAM,OAAO,CAAC,IAAI,CAAC,mBACR,MAAM,SAwBxB,CAAC"}
1
+ {"version":3,"file":"task-scheduling.d.ts","sourceRoot":"","sources":["../../../src/task-scheduling.ts"],"names":[],"mappings":"AAIA,OAAO,EAAwB,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AAEnE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAK/C,MAAM,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC;AAEvC;;;;GAIG;AAGH,qBAAa,YAAY;IAMrB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAN5B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,YAAY,CAA8B;IAClD,OAAO,CAAC,SAAS,CAAiB;gBAGf,IAAI,EAAE,OAAO,EACb,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC;IAGjD,IAAI,SAAS,YAEZ;IAED;;OAEG;IACH,QAAQ;IAuBR;;OAEG;IACG,WAAW;IASjB;;;OAGG;IACG,IAAI;CAGX;AAED,eAAO,MAAM,YAAY,QAAS,OAAO,MAAM,MAAM,IAAI,SAMxD,CAAC;AAEF,eAAO,MAAM,iBAAiB,QAAe,OAAO,MAAM,MAAM,YAAY,CAAC,IAAI,CAAC,kBAMjF,CAAC;AAEF,eAAO,MAAM,iBAAiB,QAAS,OAAO,MAAM,MAAM,YAAY,CAAC,IAAI,CAAC,SAO3E,CAAC;AAEF,eAAO,MAAM,YAAY,QAAS,OAAO,MAAM,MAAM,YAAY,CAAC,IAAI,CAAC,YAAY,MAAM,SAgBxF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,QAAS,OAAO,QAAQ,MAAM,OAAO,CAAC,IAAI,CAAC,YAAY,MAAM,SAqB7F,CAAC;AAEF,eAAO,MAAM,sCAAsC,QAC5C,OAAO,QACN,MAAM,OAAO,CAAC,IAAI,CAAC,mBACR,MAAM,SAwBxB,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":"5.7.3"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/async",
3
- "version": "0.7.4",
3
+ "version": "0.7.5-labs.071a3e2",
4
4
  "description": "Async utilities.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -28,12 +28,12 @@
28
28
  "dependencies": {
29
29
  "zen-observable": "^0.10.0",
30
30
  "zen-push": "^0.3.1",
31
- "@dxos/context": "0.7.4",
32
- "@dxos/debug": "0.7.4",
33
- "@dxos/invariant": "0.7.4",
34
- "@dxos/log": "0.7.4",
35
- "@dxos/util": "0.7.4",
36
- "@dxos/node-std": "0.7.4"
31
+ "@dxos/context": "0.7.5-labs.071a3e2",
32
+ "@dxos/invariant": "0.7.5-labs.071a3e2",
33
+ "@dxos/debug": "0.7.5-labs.071a3e2",
34
+ "@dxos/log": "0.7.5-labs.071a3e2",
35
+ "@dxos/util": "0.7.5-labs.071a3e2",
36
+ "@dxos/node-std": "0.7.5-labs.071a3e2"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@types/zen-observable": "^0.8.3"
@@ -89,6 +89,21 @@ describe('Event', () => {
89
89
  expect(error.message).to.equal('test');
90
90
  });
91
91
 
92
+ test('emitAsync', async () => {
93
+ const event = new Event<number>();
94
+ let called = 0;
95
+ event.on(async (num) => {
96
+ await sleep(10);
97
+ called++;
98
+ });
99
+
100
+ await event.emitAsync(1);
101
+ expect(called).to.equal(1);
102
+
103
+ // TODO(dmaretskyi): Disabled for now.
104
+ // expect(() => event.emit(1)).to.throw(TypeError);
105
+ });
106
+
92
107
  // test.skip('weak', async () => {
93
108
  // setFlagsFromString('--expose_gc');
94
109
  // const gc = runInNewContext('gc'); // nocommit
package/src/events.ts CHANGED
@@ -3,6 +3,7 @@
3
3
  //
4
4
 
5
5
  import { Context } from '@dxos/context';
6
+ import type { MaybePromise } from '@dxos/util';
6
7
 
7
8
  export type UnsubscribeCallback = () => void;
8
9
 
@@ -42,6 +43,11 @@ export type ListenerOptions = {
42
43
  once?: boolean;
43
44
  };
44
45
 
46
+ type EventCallback<T> = (data: T) => MaybePromise<void>;
47
+
48
+ // TODO(dmaretskyi): Remove this once the code is cleaned up.
49
+ const DO_NOT_ERROR_ON_ASYNC_CALLBACK = true;
50
+
45
51
  /**
46
52
  * An EventEmitter variant that does not do event multiplexing and represents a single event.
47
53
  *
@@ -102,7 +108,25 @@ export class Event<T = void> implements ReadOnlyEvent<T> {
102
108
  */
103
109
  emit(data: T) {
104
110
  for (const listener of this._listeners) {
105
- void listener.trigger(data);
111
+ listener.trigger(data);
112
+
113
+ if (listener.once) {
114
+ this._listeners.delete(listener);
115
+ }
116
+ }
117
+ }
118
+
119
+ /**
120
+ * Emit an event and wait for async listeners to complete.
121
+ * In most cases should only be called by the class or entity containing the event.
122
+ * All listeners are called in order of subscription with persistent ones first.
123
+ * Listeners are called sequentially.
124
+ *
125
+ * @param data param that will be passed to all listeners.
126
+ */
127
+ async emitAsync(data: T) {
128
+ for (const listener of this._listeners) {
129
+ await listener.triggerAsync(data);
106
130
 
107
131
  if (listener.once) {
108
132
  this._listeners.delete(listener);
@@ -118,9 +142,9 @@ export class Event<T = void> implements ReadOnlyEvent<T> {
118
142
  * @param options.weak If true, the callback will be weakly referenced and will be garbage collected if no other references to it exist.
119
143
  * @returns function that unsubscribes this event listener
120
144
  */
121
- on(callback: (data: T) => void): UnsubscribeCallback;
122
- on(ctx: Context, callback: (data: T) => void, options?: ListenerOptions): UnsubscribeCallback;
123
- on(_ctx: any, _callback?: (data: T) => void, options?: ListenerOptions): UnsubscribeCallback {
145
+ on(callback: EventCallback<T>): UnsubscribeCallback;
146
+ on(ctx: Context, callback: EventCallback<T>, options?: ListenerOptions): UnsubscribeCallback;
147
+ on(_ctx: any, _callback?: EventCallback<T>, options?: ListenerOptions): UnsubscribeCallback {
124
148
  const [ctx, callback] = _ctx instanceof Context ? [_ctx, _callback] : [new Context(), _ctx];
125
149
  const weak = !!options?.weak;
126
150
  const once = !!options?.once;
@@ -408,13 +432,13 @@ export interface ReadOnlyEvent<T = void> {
408
432
  }
409
433
 
410
434
  class EventListener<T> {
411
- public readonly callback: ((data: T) => void) | WeakRef<(data: T) => void>;
435
+ public readonly callback: EventCallback<T> | WeakRef<EventCallback<T>>;
412
436
 
413
437
  private readonly _clearDispose?: () => void = undefined;
414
438
 
415
439
  constructor(
416
440
  event: Event<T>,
417
- listener: (data: T) => void,
441
+ listener: EventCallback<T>,
418
442
  public readonly ctx: Context,
419
443
  public readonly once: boolean,
420
444
  public readonly weak: boolean,
@@ -438,11 +462,27 @@ class EventListener<T> {
438
462
  }
439
463
  }
440
464
 
441
- derefCallback(): ((data: T) => void) | undefined {
442
- return this.weak ? (this.callback as WeakRef<(data: T) => void>).deref() : (this.callback as (data: T) => void);
465
+ derefCallback(): EventCallback<T> | undefined {
466
+ return this.weak ? (this.callback as WeakRef<EventCallback<T>>).deref() : (this.callback as EventCallback<T>);
467
+ }
468
+
469
+ trigger(data: T) {
470
+ let result!: MaybePromise<void>;
471
+ try {
472
+ const callback = this.derefCallback();
473
+ result = callback?.(data);
474
+ } catch (err: any) {
475
+ this.ctx.raise(err);
476
+ }
477
+
478
+ if (!DO_NOT_ERROR_ON_ASYNC_CALLBACK) {
479
+ if (result instanceof Promise) {
480
+ throw new TypeError('Event has async callbacks, use emitAsync instead');
481
+ }
482
+ }
443
483
  }
444
484
 
445
- async trigger(data: T) {
485
+ async triggerAsync(data: T) {
446
486
  try {
447
487
  const callback = this.derefCallback();
448
488
  await callback?.(data);
@@ -28,6 +28,10 @@ export class DeferredTask {
28
28
  private readonly _callback: () => Promise<void>,
29
29
  ) {}
30
30
 
31
+ get scheduled() {
32
+ return this._scheduled;
33
+ }
34
+
31
35
  /**
32
36
  * Schedule the task to run asynchronously.
33
37
  */