mirror of
https://github.com/denoland/deno.git
synced 2025-02-01 20:25:12 -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:
parent
0dc2f02dfa
commit
e41af14b2a
4 changed files with 49 additions and 1 deletions
4
cli/dts/lib.deno.unstable.d.ts
vendored
4
cli/dts/lib.deno.unstable.d.ts
vendored
|
@ -1542,6 +1542,10 @@ declare namespace Deno {
|
||||||
stdout?: "piped" | "inherit" | "null";
|
stdout?: "piped" | "inherit" | "null";
|
||||||
/** Defaults to "piped". */
|
/** Defaults to "piped". */
|
||||||
stderr?: "piped" | "inherit" | "null";
|
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.
|
/** **UNSTABLE**: New API, yet to be vetted.
|
||||||
|
|
|
@ -733,7 +733,7 @@ const child = await Deno.spawnChild(Deno.execPath(), {
|
||||||
});
|
});
|
||||||
const readable = child.stdout.pipeThrough(new TextDecoderStream());
|
const readable = child.stdout.pipeThrough(new TextDecoderStream());
|
||||||
const reader = readable.getReader();
|
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
|
// to verify that stdio streams are properly unrefed
|
||||||
let count = 0;
|
let count = 0;
|
||||||
let interval;
|
let interval;
|
||||||
|
@ -787,3 +787,28 @@ setInterval(() => {
|
||||||
}, Deno.errors.NotFound);
|
}, 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");
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
stdout = "piped",
|
stdout = "piped",
|
||||||
stderr = "piped",
|
stderr = "piped",
|
||||||
signal = undefined,
|
signal = undefined,
|
||||||
|
windowsRawArguments = false,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
const child = ops.op_spawn_child({
|
const child = ops.op_spawn_child({
|
||||||
cmd: pathFromURL(command),
|
cmd: pathFromURL(command),
|
||||||
|
@ -48,6 +49,7 @@
|
||||||
stdin,
|
stdin,
|
||||||
stdout,
|
stdout,
|
||||||
stderr,
|
stderr,
|
||||||
|
windowsRawArguments,
|
||||||
}, apiName);
|
}, apiName);
|
||||||
return new Child(illegalConstructorKey, {
|
return new Child(illegalConstructorKey, {
|
||||||
...child,
|
...child,
|
||||||
|
@ -243,6 +245,7 @@
|
||||||
stdin = "null",
|
stdin = "null",
|
||||||
stdout = "piped",
|
stdout = "piped",
|
||||||
stderr = "piped",
|
stderr = "piped",
|
||||||
|
windowsRawArguments = false,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
if (stdin === "piped") {
|
if (stdin === "piped") {
|
||||||
throw new TypeError(
|
throw new TypeError(
|
||||||
|
@ -260,6 +263,7 @@
|
||||||
stdin,
|
stdin,
|
||||||
stdout,
|
stdout,
|
||||||
stderr,
|
stderr,
|
||||||
|
windowsRawArguments,
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
success: result.status.success,
|
success: result.status.success,
|
||||||
|
|
|
@ -17,6 +17,8 @@ use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
#[cfg(windows)]
|
||||||
|
use std::os::windows::process::CommandExt;
|
||||||
use std::process::ExitStatus;
|
use std::process::ExitStatus;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
@ -55,6 +57,8 @@ pub struct SpawnArgs {
|
||||||
gid: Option<u32>,
|
gid: Option<u32>,
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
uid: Option<u32>,
|
uid: Option<u32>,
|
||||||
|
#[cfg(windows)]
|
||||||
|
windows_raw_arguments: bool,
|
||||||
|
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
stdio: ChildStdio,
|
stdio: ChildStdio,
|
||||||
|
@ -131,6 +135,17 @@ fn create_command(
|
||||||
.check(&args.cmd, Some(api_name))?;
|
.check(&args.cmd, Some(api_name))?;
|
||||||
|
|
||||||
let mut command = std::process::Command::new(args.cmd);
|
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);
|
command.args(args.args);
|
||||||
|
|
||||||
if let Some(cwd) = args.cwd {
|
if let Some(cwd) = args.cwd {
|
||||||
|
|
Loading…
Add table
Reference in a new issue