Skip to content

Commit 90cc63e

Browse files
committed
feat(adb): use sticky event emitter for AdbServerClient.DeviceObserver.prototype.onListChange event
1 parent 4deb890 commit 90cc63e

File tree

5 files changed

+40
-13
lines changed

5 files changed

+40
-13
lines changed

libraries/adb-daemon-webusb/src/observer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { DeviceObserver } from "@yume-chan/adb";
2-
import { EventEmitter } from "@yume-chan/event";
2+
import { EventEmitter, StickyEventEmitter } from "@yume-chan/event";
33

44
import {
55
AdbDaemonWebUsbDevice,
@@ -34,7 +34,7 @@ export class AdbDaemonWebUsbDeviceObserver
3434
#onDeviceRemove = new EventEmitter<AdbDaemonWebUsbDevice[]>();
3535
onDeviceRemove = this.#onDeviceRemove.event;
3636

37-
#onListChange = new EventEmitter<AdbDaemonWebUsbDevice[]>();
37+
#onListChange = new StickyEventEmitter<AdbDaemonWebUsbDevice[]>();
3838
onListChange = this.#onListChange.event;
3939

4040
current: AdbDaemonWebUsbDevice[] = [];

libraries/adb/src/server/observer.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { EventEmitter } from "@yume-chan/event";
1+
import { EventEmitter, StickyEventEmitter } from "@yume-chan/event";
22

33
import { Ref } from "../utils/index.js";
44

@@ -95,6 +95,17 @@ export class AdbServerDeviceObserverOwner {
9595
throw options.signal.reason;
9696
}
9797

98+
const onDeviceAdd = new EventEmitter<AdbServerClient.Device[]>();
99+
const onDeviceRemove = new EventEmitter<AdbServerClient.Device[]>();
100+
const onListChange = new StickyEventEmitter<AdbServerClient.Device[]>();
101+
const onError = new StickyEventEmitter<Error>();
102+
103+
const observer = { onDeviceAdd, onDeviceRemove, onListChange, onError };
104+
// Register `observer` before `#connect`.
105+
// Because `#connect` might immediately receive some data
106+
// and want to trigger observers
107+
this.#observers.push(observer);
108+
98109
this.#stream ??= this.#connect();
99110
const stream = await this.#stream;
100111

@@ -103,14 +114,6 @@ export class AdbServerDeviceObserverOwner {
103114
throw options.signal.reason;
104115
}
105116

106-
const onDeviceAdd = new EventEmitter<AdbServerClient.Device[]>();
107-
const onDeviceRemove = new EventEmitter<AdbServerClient.Device[]>();
108-
const onListChange = new EventEmitter<AdbServerClient.Device[]>();
109-
const onError = new EventEmitter<Error>();
110-
111-
const observer = { onDeviceAdd, onDeviceRemove, onListChange, onError };
112-
this.#observers.push(observer);
113-
114117
const ref = new Ref(options);
115118

116119
const stop = async () => {

libraries/event/src/event-emitter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export class EventEmitter<TEvent, TResult = unknown> implements Disposable {
6262

6363
fire(e: TEvent) {
6464
for (const info of this.listeners.slice()) {
65-
info.listener.apply(info.thisArg, [e, ...info.args]);
65+
info.listener.call(info.thisArg, e, ...info.args);
6666
}
6767
}
6868

libraries/event/src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export * from "./disposable.js";
2-
export * from "./event.js";
32
export * from "./event-emitter.js";
3+
export * from "./event.js";
4+
export * from "./sticky-event-emitter.js";
45
export * from "./utils.js";
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { EventEmitter, type EventListenerInfo } from "./event-emitter.js";
2+
import type { RemoveEventListener } from "./event.js";
3+
4+
export class StickyEventEmitter<TEvent, TResult = unknown> extends EventEmitter<
5+
TEvent,
6+
TResult
7+
> {
8+
#value: TEvent | undefined;
9+
10+
protected override addEventListener(
11+
info: EventListenerInfo<TEvent, TResult>,
12+
): RemoveEventListener {
13+
if (this.#value) {
14+
info.listener.call(info.thisArg, this.#value, ...info.args);
15+
}
16+
return super.addEventListener(info);
17+
}
18+
19+
override fire(e: TEvent): void {
20+
this.#value = e;
21+
super.fire(e);
22+
}
23+
}

0 commit comments

Comments
 (0)