Description
Describe the problem
@FabianLars asked me to open a feature request, so here we are. As elaborated in #4440, there is an issue when using Tauri's JS API method shell.Child.write
: stdin is not being closed. This can make command line interfaces that depend on stdin unusable, for example esbuild
in this code snippet:
const command = Command.sidecar("../binaries/esbuild", "--loader=ts")
command.stdout.on("data", data => console.log(data))
command.stderr.on("data", data => console.log(data))
command.on("error", data => console.log(data))
command.on("close", data => console.log(data))
const child = await command.spawn()
console.log(child.pid)
await child.write("echo 'let x: number = 1'")
// => Only the pid is logged, nothing else
The expected output here would the transformed code or an error, but since stdin is not closed, no stdout/stderr is ever produced.
A workaround (credit to @lanc33llis, who faced the same issue) is this:
#[tauri::command]
async fn function(text: &str) -> Result<String, String> {
let (mut rx, mut child) = Command::new_sidecar("my-sidecar")
.expect("failed to create `my-sidecar` binary command")
.spawn()
.expect("Failed to spawn sidecar");
child.write(text.as_bytes()).expect("Failed to write to sidecar");
drop(child);
let mut output = String::new();
while let Some(event) = rx.recv().await {
if let CommandEvent::Stdout(line) = event {
output.push_str(&line);
}
}
Ok(output)
}
In my personal opinion, that workaround shouldn't be neccessary, hence this feature request.
Describe the solution you'd like
Possibly the easiest fix would be adding a closeAfter
flag to the shell.Child.write
method. This is backwards compatible and follows a similar pattern to other parts of the API.
New signature:
type WriteOptions = {closeAfter?: boolean}
write(data: string | Uint8Array, options?: WriteOptions): Promise<void>
Semantics:
If set to true, it would close stdin after writing. This would avoid adding extra methods and still allow usage such as this:
child.write("my first stdin message") // stdin is open
child.write("my second stdin message") // still open...
child.write("my final stdin message", {closeAfter: true}) // stdin is closed
Alternatives considered
A separate method for closing stdin on shell.Child
would be possible, but this would increase the API surface.
Additional context
I don't know if this problem would also appear in other parts of the JS API and would need more adjustments.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status