refactor: add readonly to many read only fields

This commit is contained in:
Simon Chan 2025-04-04 01:28:07 +08:00
parent 05c01adbd1
commit 1d71971281
No known key found for this signature in database
GPG key ID: A8B69F750B9BCEDD
18 changed files with 66 additions and 67 deletions

View file

@ -68,7 +68,7 @@ async function getAllKeys() {
* and stores them in IndexedDB. * and stores them in IndexedDB.
*/ */
export default class AdbWebCredentialStore implements AdbCredentialStore { export default class AdbWebCredentialStore implements AdbCredentialStore {
#appName: string; readonly #appName: string;
constructor(appName = "Tango") { constructor(appName = "Tango") {
this.#appName = appName; this.#appName = appName;

View file

@ -54,27 +54,27 @@ export function mergeDefaultAdbInterfaceFilter(
export class AdbDaemonWebUsbConnection export class AdbDaemonWebUsbConnection
implements ReadableWritablePair<AdbPacketData, Consumable<AdbPacketInit>> implements ReadableWritablePair<AdbPacketData, Consumable<AdbPacketInit>>
{ {
#device: AdbDaemonWebUsbDevice; readonly #device: AdbDaemonWebUsbDevice;
get device() { get device() {
return this.#device; return this.#device;
} }
#inEndpoint: USBEndpoint; readonly #inEndpoint: USBEndpoint;
get inEndpoint() { get inEndpoint() {
return this.#inEndpoint; return this.#inEndpoint;
} }
#outEndpoint: USBEndpoint; readonly #outEndpoint: USBEndpoint;
get outEndpoint() { get outEndpoint() {
return this.#outEndpoint; return this.#outEndpoint;
} }
#readable: ReadableStream<AdbPacketData>; readonly #readable: ReadableStream<AdbPacketData>;
get readable() { get readable() {
return this.#readable; return this.#readable;
} }
#writable: WritableStream<Consumable<AdbPacketInit>>; readonly #writable: WritableStream<Consumable<AdbPacketInit>>;
get writable() { get writable() {
return this.#writable; return this.#writable;
} }
@ -233,15 +233,15 @@ export class AdbDaemonWebUsbConnection
export class AdbDaemonWebUsbDevice implements AdbDaemonDevice { export class AdbDaemonWebUsbDevice implements AdbDaemonDevice {
static DeviceBusyError = _DeviceBusyError; static DeviceBusyError = _DeviceBusyError;
#interface: UsbInterfaceIdentifier; readonly #interface: UsbInterfaceIdentifier;
#usbManager: USB; readonly #usbManager: USB;
#raw: USBDevice; readonly #raw: USBDevice;
get raw() { get raw() {
return this.#raw; return this.#raw;
} }
#serial: string; readonly #serial: string;
get serial(): string { get serial(): string {
return this.#serial; return this.#serial;
} }

View file

@ -23,7 +23,7 @@ export class AdbDaemonWebUsbDeviceManager {
? new AdbDaemonWebUsbDeviceManager(globalThis.navigator.usb) ? new AdbDaemonWebUsbDeviceManager(globalThis.navigator.usb)
: undefined)(); : undefined)();
#usbManager: USB; readonly #usbManager: USB;
/** /**
* Create a new instance of {@link AdbDaemonWebUsbDeviceManager} using the specified WebUSB implementation. * Create a new instance of {@link AdbDaemonWebUsbDeviceManager} using the specified WebUSB implementation.

View file

@ -9,10 +9,10 @@ import type { AdbBanner } from "./banner.js";
import type { AdbFrameBuffer } from "./commands/index.js"; import type { AdbFrameBuffer } from "./commands/index.js";
import { import {
AdbPower, AdbPower,
AdbReverseCommand, AdbReverseService,
AdbSubprocessService, AdbSubprocessService,
AdbSync, AdbSync,
AdbTcpIpCommand, AdbTcpIpService,
escapeArg, escapeArg,
framebuffer, framebuffer,
} from "./commands/index.js"; } from "./commands/index.js";
@ -61,26 +61,29 @@ export interface AdbTransport extends Closeable {
} }
export class Adb implements Closeable { export class Adb implements Closeable {
readonly transport: AdbTransport; readonly #transport: AdbTransport;
get transport(): AdbTransport {
return this.#transport;
}
get serial() { get serial() {
return this.transport.serial; return this.#transport.serial;
} }
get maxPayloadSize() { get maxPayloadSize() {
return this.transport.maxPayloadSize; return this.#transport.maxPayloadSize;
} }
get banner() { get banner() {
return this.transport.banner; return this.#transport.banner;
} }
get disconnected() { get disconnected() {
return this.transport.disconnected; return this.#transport.disconnected;
} }
public get clientFeatures() { public get clientFeatures() {
return this.transport.clientFeatures; return this.#transport.clientFeatures;
} }
public get deviceFeatures() { public get deviceFeatures() {
@ -89,16 +92,16 @@ export class Adb implements Closeable {
readonly subprocess: AdbSubprocessService; readonly subprocess: AdbSubprocessService;
readonly power: AdbPower; readonly power: AdbPower;
readonly reverse: AdbReverseCommand; readonly reverse: AdbReverseService;
readonly tcpip: AdbTcpIpCommand; readonly tcpip: AdbTcpIpService;
constructor(transport: AdbTransport) { constructor(transport: AdbTransport) {
this.transport = transport; this.#transport = transport;
this.subprocess = new AdbSubprocessService(this); this.subprocess = new AdbSubprocessService(this);
this.power = new AdbPower(this); this.power = new AdbPower(this);
this.reverse = new AdbReverseCommand(this); this.reverse = new AdbReverseService(this);
this.tcpip = new AdbTcpIpCommand(this); this.tcpip = new AdbTcpIpService(this);
} }
canUseFeature(feature: AdbFeature): boolean { canUseFeature(feature: AdbFeature): boolean {
@ -112,7 +115,7 @@ export class Adb implements Closeable {
* Creates a new ADB Socket to the specified service or socket address. * Creates a new ADB Socket to the specified service or socket address.
*/ */
async createSocket(service: string): Promise<AdbSocket> { async createSocket(service: string): Promise<AdbSocket> {
return this.transport.connect(service); return this.#transport.connect(service);
} }
async createSocketAndWait(service: string): Promise<string> { async createSocketAndWait(service: string): Promise<string> {
@ -162,6 +165,6 @@ export class Adb implements Closeable {
} }
async close(): Promise<void> { async close(): Promise<void> {
await this.transport.close(); await this.#transport.close();
} }
} }

View file

@ -51,22 +51,22 @@ export class AdbBanner {
return new AdbBanner(product, model, device, features); return new AdbBanner(product, model, device, features);
} }
#product: string | undefined; readonly #product: string | undefined;
get product() { get product() {
return this.#product; return this.#product;
} }
#model: string | undefined; readonly #model: string | undefined;
get model() { get model() {
return this.#model; return this.#model;
} }
#device: string | undefined; readonly #device: string | undefined;
get device() { get device() {
return this.#device; return this.#device;
} }
#features: AdbFeature[] = []; readonly #features: AdbFeature[] = [];
get features() { get features() {
return this.#features; return this.#features;
} }

View file

@ -3,7 +3,7 @@ import { AutoDisposable } from "@yume-chan/event";
import type { Adb } from "../adb.js"; import type { Adb } from "../adb.js";
export class AdbServiceBase extends AutoDisposable { export class AdbServiceBase extends AutoDisposable {
#adb: Adb; readonly #adb: Adb;
get adb() { get adb() {
return this.#adb; return this.#adb;
} }

View file

@ -9,9 +9,11 @@ import {
struct, struct,
} from "@yume-chan/struct"; } from "@yume-chan/struct";
import type { Adb, AdbIncomingSocketHandler } from "../adb.js"; import type { AdbIncomingSocketHandler } from "../adb.js";
import { hexToNumber, sequenceEqual } from "../utils/index.js"; import { hexToNumber, sequenceEqual } from "../utils/index.js";
import { AdbServiceBase } from "./base.js";
export interface AdbForwardListener { export interface AdbForwardListener {
deviceSerial: string; deviceSerial: string;
@ -82,15 +84,9 @@ function decimalToNumber(buffer: Uint8Array) {
const OKAY = encodeUtf8("OKAY"); const OKAY = encodeUtf8("OKAY");
export class AdbReverseCommand { export class AdbReverseService extends AdbServiceBase {
protected adb: Adb;
readonly #deviceAddressToLocalAddress = new Map<string, string>(); readonly #deviceAddressToLocalAddress = new Map<string, string>();
constructor(adb: Adb) {
this.adb = adb;
}
protected async createBufferedStream(service: string) { protected async createBufferedStream(service: string) {
const socket = await this.adb.createSocket(service); const socket = await this.adb.createSocket(service);
return new BufferedReadableStream(socket.readable); return new BufferedReadableStream(socket.readable);

View file

@ -5,17 +5,17 @@ import { AdbNoneProtocolSubprocessService } from "./none/index.js";
import { AdbShellProtocolSubprocessService } from "./shell/index.js"; import { AdbShellProtocolSubprocessService } from "./shell/index.js";
export class AdbSubprocessService { export class AdbSubprocessService {
#adb: Adb; readonly #adb: Adb;
get adb() { get adb() {
return this.#adb; return this.#adb;
} }
#noneProtocol: AdbNoneProtocolSubprocessService; readonly #noneProtocol: AdbNoneProtocolSubprocessService;
get noneProtocol(): AdbNoneProtocolSubprocessService { get noneProtocol(): AdbNoneProtocolSubprocessService {
return this.#noneProtocol; return this.#noneProtocol;
} }
#shellProtocol?: AdbShellProtocolSubprocessService; readonly #shellProtocol?: AdbShellProtocolSubprocessService;
get shellProtocol(): AdbShellProtocolSubprocessService | undefined { get shellProtocol(): AdbShellProtocolSubprocessService | undefined {
return this.#shellProtocol; return this.#shellProtocol;
} }

View file

@ -1,5 +1,4 @@
import type { ReadableStream } from "@yume-chan/stream-extra"; import { ReadableStream } from "@yume-chan/stream-extra";
import { PushReadableStream } from "@yume-chan/stream-extra";
import type { StructValue } from "@yume-chan/struct"; import type { StructValue } from "@yume-chan/struct";
import { buffer, struct, u32 } from "@yume-chan/struct"; import { buffer, struct, u32 } from "@yume-chan/struct";
@ -52,10 +51,5 @@ export function adbSyncPull(
socket: AdbSyncSocket, socket: AdbSyncSocket,
path: string, path: string,
): ReadableStream<Uint8Array> { ): ReadableStream<Uint8Array> {
// TODO: use `ReadableStream.from` when it's supported return ReadableStream.from(adbSyncPullGenerator(socket, path));
return new PushReadableStream(async (controller) => {
for await (const data of adbSyncPullGenerator(socket, path)) {
await controller.enqueue(data);
}
});
} }

View file

@ -2,6 +2,8 @@ import { getUint32LittleEndian } from "@yume-chan/no-data-view";
import type { AsyncExactReadable, StructDeserializer } from "@yume-chan/struct"; import type { AsyncExactReadable, StructDeserializer } from "@yume-chan/struct";
import { decodeUtf8, string, struct, u32 } from "@yume-chan/struct"; import { decodeUtf8, string, struct, u32 } from "@yume-chan/struct";
import { unreachable } from "../../utils/no-op.js";
function encodeAsciiUnchecked(value: string): Uint8Array { function encodeAsciiUnchecked(value: string): Uint8Array {
const result = new Uint8Array(value.length); const result = new Uint8Array(value.length);
for (let i = 0; i < value.length; i += 1) { for (let i = 0; i < value.length; i += 1) {
@ -83,7 +85,7 @@ export async function* adbSyncReadResponses<T>(
switch (getUint32LittleEndian(buffer, 0)) { switch (getUint32LittleEndian(buffer, 0)) {
case AdbSyncResponseId.Fail: case AdbSyncResponseId.Fail:
await AdbSyncFailResponse.deserialize(stream); await AdbSyncFailResponse.deserialize(stream);
throw new Error("Unreachable"); unreachable();
case AdbSyncResponseId.Done: case AdbSyncResponseId.Done:
// `DONE` responses' size are always same as the request's normal response. // `DONE` responses' size are always same as the request's normal response.
// //

View file

@ -27,7 +27,7 @@ function parsePort(value: string): number | undefined {
return Number.parseInt(value, 10); return Number.parseInt(value, 10);
} }
export class AdbTcpIpCommand extends AdbServiceBase { export class AdbTcpIpService extends AdbServiceBase {
async getListenAddresses(): Promise<AdbTcpIpListenAddresses> { async getListenAddresses(): Promise<AdbTcpIpListenAddresses> {
const serviceListenAddresses = await this.adb.getProp( const serviceListenAddresses = await this.adb.getProp(
"service.adb.listen_addrs", "service.adb.listen_addrs",

View file

@ -101,18 +101,21 @@ export class AdbPacketDispatcher implements Closeable {
*/ */
readonly #sockets = new Map<number, AdbDaemonSocketController>(); readonly #sockets = new Map<number, AdbDaemonSocketController>();
#writer: WritableStreamDefaultWriter<Consumable<AdbPacketInit>>; readonly #writer: WritableStreamDefaultWriter<Consumable<AdbPacketInit>>;
readonly options: AdbPacketDispatcherOptions; readonly options: AdbPacketDispatcherOptions;
#closed = false; #closed = false;
#disconnected = new PromiseResolver<void>(); readonly #disconnected = new PromiseResolver<void>();
get disconnected() { get disconnected() {
return this.#disconnected.promise; return this.#disconnected.promise;
} }
#incomingSocketHandlers = new Map<string, AdbIncomingSocketHandler>(); readonly #incomingSocketHandlers = new Map<
#readAbortController = new AbortController(); string,
AdbIncomingSocketHandler
>();
readonly #readAbortController = new AbortController();
constructor( constructor(
connection: ReadableWritablePair< connection: ReadableWritablePair<

View file

@ -43,7 +43,7 @@ export class AdbDaemonSocketController
readonly localCreated!: boolean; readonly localCreated!: boolean;
readonly service!: string; readonly service!: string;
#readable: ReadableStream<Uint8Array>; readonly #readable: ReadableStream<Uint8Array>;
#readableController!: PushReadableStreamController<Uint8Array>; #readableController!: PushReadableStreamController<Uint8Array>;
get readable() { get readable() {
return this.#readable; return this.#readable;
@ -54,12 +54,12 @@ export class AdbDaemonSocketController
#closed = false; #closed = false;
#closedPromise = new PromiseResolver<undefined>(); readonly #closedPromise = new PromiseResolver<undefined>();
get closed() { get closed() {
return this.#closedPromise.promise; return this.#closedPromise.promise;
} }
#socket: AdbDaemonSocket; readonly #socket: AdbDaemonSocket;
get socket() { get socket() {
return this.#socket; return this.#socket;
} }
@ -178,7 +178,7 @@ export class AdbDaemonSocketController
* A duplex stream representing a socket to ADB daemon. * A duplex stream representing a socket to ADB daemon.
*/ */
export class AdbDaemonSocket implements AdbDaemonSocketInfo, AdbSocket { export class AdbDaemonSocket implements AdbDaemonSocketInfo, AdbSocket {
#controller: AdbDaemonSocketController; readonly #controller: AdbDaemonSocketController;
get localId(): number { get localId(): number {
return this.#controller.localId; return this.#controller.localId;

View file

@ -112,7 +112,7 @@ export class AdbServerClient {
readonly wireless = new WirelessCommands(this); readonly wireless = new WirelessCommands(this);
readonly mDns = new MDnsCommands(this); readonly mDns = new MDnsCommands(this);
#observerOwner = new AdbServerDeviceObserverOwner(this); readonly #observerOwner = new AdbServerDeviceObserverOwner(this);
constructor(connector: AdbServerClient.ServerConnector) { constructor(connector: AdbServerClient.ServerConnector) {
this.connector = connector; this.connector = connector;

View file

@ -3,7 +3,7 @@
import type { AdbServerClient } from "../client.js"; import type { AdbServerClient } from "../client.js";
export class MDnsCommands { export class MDnsCommands {
#client: AdbServerClient; readonly #client: AdbServerClient;
constructor(client: AdbServerClient) { constructor(client: AdbServerClient) {
this.#client = client; this.#client = client;

View file

@ -26,7 +26,7 @@ export class AlreadyConnectedError extends Error {
} }
export class WirelessCommands { export class WirelessCommands {
#client: AdbServerClient; readonly #client: AdbServerClient;
constructor(client: AdbServerClient) { constructor(client: AdbServerClient) {
this.#client = client; this.#client = client;

View file

@ -9,7 +9,7 @@ import type {
import { byobFieldSerializer, defaultFieldSerializer } from "./serialize.js"; import { byobFieldSerializer, defaultFieldSerializer } from "./serialize.js";
import type { Field, FieldDeserializeContext, FieldOptions } from "./types.js"; import type { Field, FieldDeserializeContext, FieldOptions } from "./types.js";
export type MaybeBipedalFieldDeserializer<T, D> = BipedalGenerator< export type BipedalFieldDeserializer<T, D> = BipedalGenerator<
undefined, undefined,
T, T,
[reader: AsyncExactReadable, context: FieldDeserializeContext<D>] [reader: AsyncExactReadable, context: FieldDeserializeContext<D>]
@ -20,7 +20,7 @@ function _field<T, OmitInit extends string, D, Raw = T>(
size: number, size: number,
type: "default", type: "default",
serialize: DefaultFieldSerializer<Raw>, serialize: DefaultFieldSerializer<Raw>,
deserialize: MaybeBipedalFieldDeserializer<T, D>, deserialize: BipedalFieldDeserializer<T, D>,
options?: FieldOptions<T, OmitInit, D, Raw>, options?: FieldOptions<T, OmitInit, D, Raw>,
): Field<T, OmitInit, D, Raw>; ): Field<T, OmitInit, D, Raw>;
// eslint-disable-next-line @typescript-eslint/max-params // eslint-disable-next-line @typescript-eslint/max-params
@ -28,7 +28,7 @@ function _field<T, OmitInit extends string, D, Raw = T>(
size: number, size: number,
type: "byob", type: "byob",
serialize: ByobFieldSerializer<Raw>, serialize: ByobFieldSerializer<Raw>,
deserialize: MaybeBipedalFieldDeserializer<T, D>, deserialize: BipedalFieldDeserializer<T, D>,
options?: FieldOptions<T, OmitInit, D, Raw>, options?: FieldOptions<T, OmitInit, D, Raw>,
): Field<T, OmitInit, D, Raw>; ): Field<T, OmitInit, D, Raw>;
/* #__NO_SIDE_EFFECTS__ */ /* #__NO_SIDE_EFFECTS__ */
@ -37,7 +37,7 @@ function _field<T, OmitInit extends string, D, Raw = T>(
size: number, size: number,
type: "default" | "byob", type: "default" | "byob",
serialize: DefaultFieldSerializer<Raw> | ByobFieldSerializer<Raw>, serialize: DefaultFieldSerializer<Raw> | ByobFieldSerializer<Raw>,
deserialize: MaybeBipedalFieldDeserializer<T, D>, deserialize: BipedalFieldDeserializer<T, D>,
options?: FieldOptions<T, OmitInit, D, Raw>, options?: FieldOptions<T, OmitInit, D, Raw>,
): Field<T, OmitInit, D, Raw> { ): Field<T, OmitInit, D, Raw> {
const field: Field<T, OmitInit, D, Raw> = { const field: Field<T, OmitInit, D, Raw> = {

View file

@ -25,6 +25,7 @@ export default tslint.config(
maxBOF: 0, maxBOF: 0,
}, },
], ],
"no-fallthrough": "off",
}, },
}, },
...tslint.configs.recommendedTypeChecked, ...tslint.configs.recommendedTypeChecked,