I'm trying to have deno output some information to file descriptor 3, so I am spawning deno like so:
$ deno run example.ts 3>three.txt
I have it working as expected by using /dev/fd/3:
const fd = Deno.openSync('/dev/fd/3', { read: false, write: true });
Deno.writeAllSync(fd, new TextEncoder().encode('hello'));
Deno.close(fd.rid);
Ok fine, good. But what I am really interested is learning the proper way to do this in a cross-platform way that will work on Windows.
Thanks in advance!
Deno doesn't expose file descriptors directly to the runtime - the resource ids often overlap but are not identical to FDs. I'm sorry to report that currently there's no way to do this.
Is this actually important? It's not inconceivable that we could make this work - but I'd like to understand the use-case better before dedicating time to it.
Really I'm just looking for a cross-platform solution (for Windows specifically) to /dev/fd/3.
Really I'm just looking for a cross-platform solution (for Windows specifically) to
/dev/fd/3.
AFAIK, Windows doesn't have file descriptors. Also, there is no /dev/fd/3 device file (though other device files, such as, CON do exist).
May I ask why you want to write to /dev/fd/3?
PS: The Microsoft Visual C Runtime (MSVCRT) does provide an abstraction layer over Windows file handles so you can work with them similar to Unix file descriptors. I'm not aware of it abstracting /dev/**/**, though.
$ deno run example.ts 3>three.txt
In cmd.exe, handle no. 3 is a user-defined handle: https://web.archive.org/web/20171225062127id_/http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/redirection.mspx?mfr=true
In powershell.exe, it is the "warning stream": https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_redirection
May I ask why you want to write to
/dev/fd/3?
I am passing structured data back up to the parent process, but can't use stdout in this case since this Deno script is importing other user code that will want to use stdout for their own purposes.
$ deno run example.ts 3>three.txt
That syntax I used was for Bash, as an example, but in reality I'm spawning Deno through a Node.js script doing something like this:
const child = spawn('deno', ['run', 'script.ts'], {
stdio: ['ignore', 'inherit', 'inherit', 'pipe']
});
Notice the "pipe" for the FD 3, which causes child.stdio[3] to be a Readable stream to read out what the deno script writes to FD 3.
Notice the "pipe" for the FD 3, which causes child.stdio[3] to be a Readable stream
Is that stream readable from runtimes other than Node? And if so, how? I'm not sure how that works.
As an alternative, you could use alternate data streams. They work on NTFS, the main Windows file system.
// parent.js
const fs = require("fs");
const child_process = require("child_process");
fs.writeFileSync("child.ts", `Deno.writeTextFileSync("child.ts:stream", "hello parent");`);
child_process.spawnSync("deno", ["run", "--allow-write", "child.ts"]);
console.log(fs.readFileSync("child.ts:stream").toString("utf-8"));
> node parent.js
hello parent
Here is a comment about making the setup I'm trying to achieve work in Go: https://github.com/golang/go/issues/21085#issuecomment-368653216 (the entire issue seems relevant actually)