0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-02-01 12:16:11 -05:00

feat(unstable): add windowsRawArguments to SpawnOptions (#16319)

This change adds `windowsRawArguments` to `SpawnOptions`. The option enables
skipping the default quoting and escaping while creating the command on
windows.

The option works in a similar way as `windowsVerbatimArguments` in
child_process.spawn options in Node.js, and is necessary for simulating
it in `std/node`.

closes #8852
This commit is contained in:
Yoshiya Hinosawa 2022-10-17 19:51:25 +09:00 committed by GitHub
parent 0dc2f02dfa
commit e41af14b2a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 49 additions and 1 deletions

View file

@ -1542,6 +1542,10 @@ declare namespace Deno {
stdout?: "piped" | "inherit" | "null";
/** Defaults to "piped". */
stderr?: "piped" | "inherit" | "null";
/** Skips quoting and escaping of the arguments on windows. This option
* is ignored on non-windows platforms. Defaults to "false". */
windowsRawArguments?: boolean;
}
/** **UNSTABLE**: New API, yet to be vetted.

View file

@ -733,7 +733,7 @@ const child = await Deno.spawnChild(Deno.execPath(), {
});
const readable = child.stdout.pipeThrough(new TextDecoderStream());
const reader = readable.getReader();
// set up an interval that will end after reading a few messages from stdout,
// set up an interval that will end after reading a few messages from stdout,
// to verify that stdio streams are properly unrefed
let count = 0;
let interval;
@ -787,3 +787,28 @@ setInterval(() => {
}, Deno.errors.NotFound);
},
);
Deno.test(
{ ignore: Deno.build.os !== "windows" },
async function spawnWindowsRawArguments() {
let { success, stdout } = await Deno.spawn("cmd", {
args: ["/d", "/s", "/c", '"deno ^"--version^""'],
windowsRawArguments: true,
});
assert(success);
let stdoutText = new TextDecoder().decode(stdout);
assertStringIncludes(stdoutText, "deno");
assertStringIncludes(stdoutText, "v8");
assertStringIncludes(stdoutText, "typescript");
({ success, stdout } = Deno.spawnSync("cmd", {
args: ["/d", "/s", "/c", '"deno ^"--version^""'],
windowsRawArguments: true,
}));
assert(success);
stdoutText = new TextDecoder().decode(stdout);
assertStringIncludes(stdoutText, "deno");
assertStringIncludes(stdoutText, "v8");
assertStringIncludes(stdoutText, "typescript");
},
);

View file

@ -36,6 +36,7 @@
stdout = "piped",
stderr = "piped",
signal = undefined,
windowsRawArguments = false,
} = {}) {
const child = ops.op_spawn_child({
cmd: pathFromURL(command),
@ -48,6 +49,7 @@
stdin,
stdout,
stderr,
windowsRawArguments,
}, apiName);
return new Child(illegalConstructorKey, {
...child,
@ -243,6 +245,7 @@
stdin = "null",
stdout = "piped",
stderr = "piped",
windowsRawArguments = false,
} = {}) {
if (stdin === "piped") {
throw new TypeError(
@ -260,6 +263,7 @@
stdin,
stdout,
stderr,
windowsRawArguments,
});
return {
success: result.status.success,

View file

@ -17,6 +17,8 @@ use serde::Deserialize;
use serde::Serialize;
use std::borrow::Cow;
use std::cell::RefCell;
#[cfg(windows)]
use std::os::windows::process::CommandExt;
use std::process::ExitStatus;
use std::rc::Rc;
@ -55,6 +57,8 @@ pub struct SpawnArgs {
gid: Option<u32>,
#[cfg(unix)]
uid: Option<u32>,
#[cfg(windows)]
windows_raw_arguments: bool,
#[serde(flatten)]
stdio: ChildStdio,
@ -131,6 +135,17 @@ fn create_command(
.check(&args.cmd, Some(api_name))?;
let mut command = std::process::Command::new(args.cmd);
#[cfg(windows)]
if args.windows_raw_arguments {
for arg in args.args.iter() {
command.raw_arg(arg);
}
} else {
command.args(args.args);
}
#[cfg(not(windows))]
command.args(args.args);
if let Some(cwd) = args.cwd {