diff --git a/cli/dts/lib.deno.ns.d.ts b/cli/dts/lib.deno.ns.d.ts index 37cc58ad6b..e1aff59fc9 100644 --- a/cli/dts/lib.deno.ns.d.ts +++ b/cli/dts/lib.deno.ns.d.ts @@ -2034,6 +2034,10 @@ declare namespace Deno { * Subprocess uses same working directory as parent process unless `opt.cwd` * is specified. * + * Environmental variables from parent process can be cleared using `opt.clearEnv`. + * Doesn't guarantee that only `opt.env` variables are present, + * as the OS may set environmental variables for processes. + * * Environmental variables for subprocess can be specified using `opt.env` * mapping. * diff --git a/cli/dts/lib.deno.unstable.d.ts b/cli/dts/lib.deno.unstable.d.ts index 0ac8294637..6fbd13f5f2 100644 --- a/cli/dts/lib.deno.unstable.d.ts +++ b/cli/dts/lib.deno.unstable.d.ts @@ -791,6 +791,14 @@ declare namespace Deno { mtime: number | Date, ): Promise; + export function run< + T extends RunOptions & { + clearEnv?: boolean; + } = RunOptions & { + clearEnv?: boolean; + }, + >(opt: T): Process; + /** **UNSTABLE**: The `signo` argument may change to require the Deno.Signal * enum. * diff --git a/cli/tests/unit/process_test.ts b/cli/tests/unit/process_test.ts index 9bb4d7fc20..f187efe71c 100644 --- a/cli/tests/unit/process_test.ts +++ b/cli/tests/unit/process_test.ts @@ -510,3 +510,31 @@ unitTest({ perms: { run: true, read: true } }, function killFailed(): void { p.close(); }); + +unitTest( + { perms: { run: true, read: true, env: true } }, + async function clearEnv(): Promise { + const p = Deno.run({ + cmd: [ + Deno.execPath(), + "eval", + "-p", + "JSON.stringify(Deno.env.toObject())", + ], + stdout: "piped", + clearEnv: true, + env: { + FOO: "23147", + }, + }); + + const obj = JSON.parse(new TextDecoder().decode(await p.output())); + + // can't check for object equality because the OS may set additional env vars for processes + // so we check if PATH isn't present as that is a common env var across OS's and isn't set for processes. + assertEquals(obj.FOO, "23147"); + assert(!("PATH" in obj)); + + p.close(); + }, +); diff --git a/runtime/js/40_process.js b/runtime/js/40_process.js index 70a590f36d..543c53c271 100644 --- a/runtime/js/40_process.js +++ b/runtime/js/40_process.js @@ -100,6 +100,7 @@ function run({ cmd, cwd = undefined, + clearEnv = false, env = {}, stdout = "inherit", stderr = "inherit", @@ -111,6 +112,7 @@ const res = opRun({ cmd: ArrayPrototypeMap(cmd, String), cwd, + clearEnv, env: ObjectEntries(env), stdin: isRid(stdin) ? "" : stdin, stdout: isRid(stdout) ? "" : stdout, diff --git a/runtime/ops/process.rs b/runtime/ops/process.rs index 679deff98c..0f0cc6e2a0 100644 --- a/runtime/ops/process.rs +++ b/runtime/ops/process.rs @@ -61,6 +61,7 @@ fn subprocess_stdio_map(s: &str) -> Result { pub struct RunArgs { cmd: Vec, cwd: Option, + clear_env: bool, env: Vec<(String, String)>, stdin: String, stdout: String, @@ -113,6 +114,11 @@ fn op_run( c.arg(arg); }); cwd.map(|d| c.current_dir(d)); + + if run_args.clear_env { + super::check_unstable(state, "Deno.run.clearEnv"); + c.env_clear(); + } for (key, value) in &env { c.env(key, value); }