Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit 0af52800 authored by Simon Chan's avatar Simon Chan
Browse files

feat(adb): allow killing subprocess using an AbortSignal

parent 029d72e6
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -24,11 +24,13 @@ export interface AdbSubprocessOptions {
     * @default [AdbSubprocessShellProtocol, AdbSubprocessNoneProtocol]
     */
    protocols: AdbSubprocessProtocolConstructor[];

    signal?: AbortSignal;
}

const DEFAULT_OPTIONS: AdbSubprocessOptions = {
const DEFAULT_OPTIONS = {
    protocols: [AdbSubprocessShellProtocol, AdbSubprocessNoneProtocol],
};
} satisfies AdbSubprocessOptions;

export interface AdbSubprocessWaitResult {
    stdout: string;
@@ -42,7 +44,7 @@ export class AdbSubprocess extends AdbCommandBase {
        command?: string | string[],
        options?: Partial<AdbSubprocessOptions>,
    ): Promise<AdbSubprocessProtocol> {
        const { protocols } = { ...DEFAULT_OPTIONS, ...options };
        const { protocols, signal } = { ...DEFAULT_OPTIONS, ...options };

        let Constructor: AdbSubprocessProtocolConstructor | undefined;
        for (const item of protocols) {
@@ -63,7 +65,7 @@ export class AdbSubprocess extends AdbCommandBase {
            // spawn the default shell
            command = "";
        }
        return await Constructor[mode](this.adb, command);
        return await Constructor[mode](this.adb, command, signal);
    }

    /**
+8 −3
Original line number Diff line number Diff line
@@ -18,17 +18,19 @@ export class AdbSubprocessNoneProtocol implements AdbSubprocessProtocol {
        return true;
    }

    static async pty(adb: Adb, command: string) {
    static async pty(adb: Adb, command: string, signal?: AbortSignal) {
        return new AdbSubprocessNoneProtocol(
            await adb.createSocket(`shell:${command}`),
            signal,
        );
    }

    static async raw(adb: Adb, command: string) {
    static async raw(adb: Adb, command: string, signal?: AbortSignal) {
        // `shell,raw:${command}` also triggers raw mode,
        // But is not supported on Android version <7.
        return new AdbSubprocessNoneProtocol(
            await adb.createSocket(`exec:${command}`),
            signal,
        );
    }

@@ -59,8 +61,11 @@ export class AdbSubprocessNoneProtocol implements AdbSubprocessProtocol {
        return this.#exit;
    }

    constructor(socket: AdbSocket) {
    constructor(socket: AdbSocket, signal?: AbortSignal) {
        signal?.throwIfAborted();

        this.#socket = socket;
        signal?.addEventListener("abort", () => void this.kill());

        this.#stderr = new ReadableStream({
            start: async (controller) => {
+8 −3
Original line number Diff line number Diff line
@@ -55,16 +55,18 @@ export class AdbSubprocessShellProtocol implements AdbSubprocessProtocol {
        return adb.canUseFeature(AdbFeature.ShellV2);
    }

    static async pty(adb: Adb, command: string) {
    static async pty(adb: Adb, command: string, signal?: AbortSignal) {
        // TODO: AdbShellSubprocessProtocol: Support setting `XTERM` environment variable
        return new AdbSubprocessShellProtocol(
            await adb.createSocket(`shell,v2,pty:${command}`),
            signal,
        );
    }

    static async raw(adb: Adb, command: string) {
    static async raw(adb: Adb, command: string, signal?: AbortSignal) {
        return new AdbSubprocessShellProtocol(
            await adb.createSocket(`shell,v2,raw:${command}`),
            signal,
        );
    }

@@ -91,8 +93,11 @@ export class AdbSubprocessShellProtocol implements AdbSubprocessProtocol {
        return this.#exit.promise;
    }

    constructor(socket: AdbSocket) {
    constructor(socket: AdbSocket, signal?: AbortSignal) {
        signal?.throwIfAborted();

        this.#socket = socket;
        signal?.addEventListener("abort", () => void this.kill());

        let stdoutController!: PushReadableStreamController<Uint8Array>;
        let stderrController!: PushReadableStreamController<Uint8Array>;
+10 −2
Original line number Diff line number Diff line
@@ -53,10 +53,18 @@ export interface AdbSubprocessProtocolConstructor {
    isSupported(adb: Adb): MaybePromiseLike<boolean>;

    /** Spawns an executable in PTY (interactive) mode. */
    pty(adb: Adb, command: string): MaybePromiseLike<AdbSubprocessProtocol>;
    pty: (
        adb: Adb,
        command: string,
        signal?: AbortSignal,
    ) => MaybePromiseLike<AdbSubprocessProtocol>;

    /** Spawns an executable and pipe the output. */
    raw(adb: Adb, command: string): MaybePromiseLike<AdbSubprocessProtocol>;
    raw(
        adb: Adb,
        command: string,
        signal?: AbortSignal,
    ): MaybePromiseLike<AdbSubprocessProtocol>;

    /** Creates a new `AdbShell` by attaching to an exist `AdbSocket` */
    new (socket: AdbSocket): AdbSubprocessProtocol;
+0 −2
Original line number Diff line number Diff line
@@ -80,13 +80,11 @@ export type LogcatFormat = (typeof LogcatFormat)[keyof typeof LogcatFormat];
export interface LogcatFormatModifiers {
    microseconds?: boolean;
    nanoseconds?: boolean;
    printable?: boolean;
    year?: boolean;
    timezone?: boolean;
    epoch?: boolean;
    monotonic?: boolean;
    uid?: boolean;
    descriptive?: boolean;
}

export interface LogcatOptions {
Loading