deno_std icon indicating copy to clipboard operation
deno_std copied to clipboard

`@std/cli/unstable-progress-bar` pipeTo promise is ignored

Open nsf opened this issue 9 months ago • 0 comments

The following code:

import { ProgressBar } from "@std/cli/unstable-progress-bar";

const pb1 = new ProgressBar(Deno.stdout.writable, { max: 5 });
pb1.add(5);
await pb1.end();
const pb2 = new ProgressBar(Deno.stdout.writable, { max: 5 });
pb2.add(5);
await pb2.end();

fails with:

[00:00] [##################################################] [0.00/0.00 KiB]
error: Top-level await promise never resolved
await pb2.end();
^
    at <anonymous> (file:///home/nsf/tmp/denotest/main.ts:8:1)

I think this is because returned pipeTo promise here: https://github.com/denoland/std/blob/14b96c6efe09b30e0348aab01ab3f717f80f6d73/cli/unstable_progress_bar.ts#L187-L189 is ignored and never awaited. Debugging shows "writer already locked" messages. I believe this is because internally pipeTo does getWriter() and releases the lock on close(), but you need to await for it.

The fix might look like so:

  1. Add #pipePromise: Promise<void>; member to the ProgressBar class.
  2. Store the pipeTo promise:
    this.#pipePromise = stream.readable
      .pipeTo(writable, { preventClose: this.#options.keepOpen })
      .catch(() => clearInterval(this.#id));
    
  3. Await for it in end():
    await this.#print()
      .then(() => this.#writer.write(this.#options.clear ? "\r\u001b[K" : "\n"))
      .then(() => this.#writer.close())
      .then(() => this.#pipePromise)
      .catch(() => {});
    

nsf avatar Mar 10 '25 07:03 nsf