deno
deno copied to clipboard
Writable Stream API is Broken for Stdout and Stderr (Async IO)
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.
The writable stream API also does not have a writeSync
method, which is useful when using the writers for logging.
Possibly related #22159
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.