refactor: use ES private fields to replace TypeScript private accessors

This commit is contained in:
Simon Chan 2023-05-25 23:00:08 +08:00
parent b87d76ca6e
commit d286a40c42
No known key found for this signature in database
GPG key ID: A8B69F750B9BCEDD
28 changed files with 434 additions and 442 deletions

View file

@ -43,28 +43,24 @@ export interface AdbPacketDispatcherOptions {
export class AdbPacketDispatcher implements Closeable {
// ADB socket id starts from 1
// (0 means open failed)
private readonly initializers = new AsyncOperationManager(1);
readonly #initializers = new AsyncOperationManager(1);
/**
* Socket local ID to the socket controller.
*/
private readonly sockets = new Map<number, AdbDaemonSocketController>();
readonly #sockets = new Map<number, AdbDaemonSocketController>();
private _writer: WritableStreamDefaultWriter<Consumable<AdbPacketInit>>;
#writer: WritableStreamDefaultWriter<Consumable<AdbPacketInit>>;
public readonly options: AdbPacketDispatcherOptions;
private _closed = false;
private _disconnected = new PromiseResolver<void>();
#closed = false;
#disconnected = new PromiseResolver<void>();
public get disconnected() {
return this._disconnected.promise;
return this.#disconnected.promise;
}
private _incomingSocketHandlers = new Map<
string,
AdbIncomingSocketHandler
>();
private _abortController = new AbortController();
#incomingSocketHandlers = new Map<string, AdbIncomingSocketHandler>();
#readAbortController = new AbortController();
public constructor(
connection: ReadableWritablePair<
@ -87,8 +83,8 @@ export class AdbPacketDispatcher implements Closeable {
await this.handleClose(packet);
break;
case AdbCommand.Write:
if (this.sockets.has(packet.arg1)) {
await this.sockets
if (this.#sockets.has(packet.arg1)) {
await this.#sockets
.get(packet.arg1)!
.enqueue(packet.payload);
await this.sendPacket(
@ -124,7 +120,7 @@ export class AdbPacketDispatcher implements Closeable {
// it's still possible to create another ADB connection.
// So don't close `readable` here.
preventCancel: true,
signal: this._abortController.signal,
signal: this.#readAbortController.signal,
}
)
.then(
@ -132,23 +128,23 @@ export class AdbPacketDispatcher implements Closeable {
this.dispose();
},
(e) => {
if (!this._closed) {
this._disconnected.reject(e);
if (!this.#closed) {
this.#disconnected.reject(e);
}
this.dispose();
}
);
this._writer = connection.writable.getWriter();
this.#writer = connection.writable.getWriter();
}
private handleOk(packet: AdbPacketData) {
if (this.initializers.resolve(packet.arg1, packet.arg0)) {
if (this.#initializers.resolve(packet.arg1, packet.arg0)) {
// Device successfully created the socket
return;
}
const socket = this.sockets.get(packet.arg1);
const socket = this.#sockets.get(packet.arg1);
if (socket) {
// Device has received last `WRTE` to the socket
socket.ack();
@ -164,7 +160,7 @@ export class AdbPacketDispatcher implements Closeable {
// If the socket is still pending
if (
packet.arg0 === 0 &&
this.initializers.reject(
this.#initializers.reject(
packet.arg1,
new Error("Socket open failed")
)
@ -185,7 +181,7 @@ export class AdbPacketDispatcher implements Closeable {
*/
// Ignore `arg0` and search for the socket
const socket = this.sockets.get(packet.arg1);
const socket = this.#sockets.get(packet.arg1);
if (socket) {
// The device want to close the socket
if (!socket.closed) {
@ -196,7 +192,7 @@ export class AdbPacketDispatcher implements Closeable {
);
}
await socket.dispose();
this.sockets.delete(packet.arg1);
this.#sockets.delete(packet.arg1);
return;
}
@ -209,22 +205,22 @@ export class AdbPacketDispatcher implements Closeable {
service: string,
handler: AdbIncomingSocketHandler
) {
this._incomingSocketHandlers.set(service, handler);
this.#incomingSocketHandlers.set(service, handler);
}
public removeReverseTunnel(address: string) {
this._incomingSocketHandlers.delete(address);
this.#incomingSocketHandlers.delete(address);
}
public clearReverseTunnels() {
this._incomingSocketHandlers.clear();
this.#incomingSocketHandlers.clear();
}
private async handleOpen(packet: AdbPacketData) {
// `AsyncOperationManager` doesn't support skipping IDs
// Use `add` + `resolve` to simulate this behavior
const [localId] = this.initializers.add<number>();
this.initializers.resolve(localId, undefined);
const [localId] = this.#initializers.add<number>();
this.#initializers.resolve(localId, undefined);
const remoteId = packet.arg0;
let service = decodeUtf8(packet.payload);
@ -232,7 +228,7 @@ export class AdbPacketDispatcher implements Closeable {
service = service.substring(0, service.length - 1);
}
const handler = this._incomingSocketHandlers.get(service);
const handler = this.#incomingSocketHandlers.get(service);
if (!handler) {
await this.sendPacket(AdbCommand.Close, 0, remoteId);
return;
@ -248,7 +244,7 @@ export class AdbPacketDispatcher implements Closeable {
try {
await handler(controller.socket);
this.sockets.set(localId, controller);
this.#sockets.set(localId, controller);
await this.sendPacket(AdbCommand.OK, localId, remoteId);
} catch (e) {
await this.sendPacket(AdbCommand.Close, 0, remoteId);
@ -260,7 +256,7 @@ export class AdbPacketDispatcher implements Closeable {
service += "\0";
}
const [localId, initializer] = this.initializers.add<number>();
const [localId, initializer] = this.#initializers.add<number>();
await this.sendPacket(AdbCommand.Open, localId, 0, service);
// Fulfilled by `handleOk`
@ -272,7 +268,7 @@ export class AdbPacketDispatcher implements Closeable {
localCreated: true,
service,
});
this.sockets.set(localId, controller);
this.#sockets.set(localId, controller);
return controller.socket;
}
@ -291,7 +287,7 @@ export class AdbPacketDispatcher implements Closeable {
throw new Error("payload too large");
}
await ConsumableWritableStream.write(this._writer, {
await ConsumableWritableStream.write(this.#writer, {
command,
arg0,
arg1,
@ -306,24 +302,24 @@ export class AdbPacketDispatcher implements Closeable {
public async close() {
// Send `CLSE` packets for all sockets
await Promise.all(
Array.from(this.sockets.values(), (socket) => socket.close())
Array.from(this.#sockets.values(), (socket) => socket.close())
);
// Stop receiving
// It's possible that we haven't received all `CLSE` confirm packets,
// but it doesn't matter, the next connection can cope with them.
this._closed = true;
this._abortController.abort();
this._writer.releaseLock();
this.#closed = true;
this.#readAbortController.abort();
this.#writer.releaseLock();
// `pipe().then()` will call `dispose`
}
private dispose() {
for (const socket of this.sockets.values()) {
for (const socket of this.#sockets.values()) {
socket.dispose().catch(unreachable);
}
this._disconnected.resolve();
this.#disconnected.resolve();
}
}