deno icon indicating copy to clipboard operation
deno copied to clipboard

Writable Stream API is Broken for Stdout and Stderr (Async IO)

Open j50n opened this issue 1 year ago • 3 comments

Version: Deno 1.39.0

This has become a problem because Writer is deprecated now. This means that stdout and stderr can't have a Writer interface anymore.

This code will fail with an error on one of the two calls to getWriter().

import { sleep } from "../mod.ts";

await Promise.all([
  (async () => {
    const writer = Deno.stdout.writable.getWriter();
    console.error("got 1");
    try {
      for (let i = 0; i < 10; i += 2) {
        await writer.write(new TextEncoder().encode(`${i}\n`));
        await sleep(1000);
      }
    } finally {
      writer.releaseLock();
    }
  })(),
  (async () => {
    const writer = Deno.stdout.writable.getWriter();
    console.error("got 2");
    try {
      for (let i = 1; i < 10; i += 2) {
        await writer.write(new TextEncoder().encode(`${i}\n`));
        await sleep(1000);
      }
    } finally {
      writer.releaseLock();
    }
  })(),
]);

This is a problem if different libraries try to use this to write to stdout asynchronously.

My understanding of stdout and stderr is that writes to these should pretty much never fail, and should be available to any part of the application. One part of the application should not be able to block access to stdout or stderr in another part, asynchronous or synchronous.

My first thought on this is that this could be solved by removing writable from stdout/stderr and making stdout/stderr a full WritableStreamDefaultWriter, where they are both currently Writer and WriterSync now. That would be a pretty bad break of the API though, I realize. No way to make it backward compatible, as some of the method names overlap.

I discovered this problem a while back, but it has become more of a problem now that Writer is going away. I was able to legally work around it until now.

j50n avatar Dec 19 '23 02:12 j50n

The writable stream API also does not have a writeSync method, which is useful when using the writers for logging.

mdekstrand avatar Jan 30 '24 13:01 mdekstrand

Possibly related #22159

iuioiua avatar Jan 30 '24 14:01 iuioiua

Deno.stdout and friends won't have their write(), read() and other methods removed. They're just no longer going to explicitly implement the Deno.Writer and other interfaces anymore. I understand the confusion, though.

iuioiua avatar Jan 30 '24 23:01 iuioiua