diff options
author | Bartek IwaĆczuk <biwanczuk@gmail.com> | 2022-11-10 22:03:28 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-10 22:03:28 +0100 |
commit | 8d5c0112fbbed188f97218ace2357feba3a8746f (patch) | |
tree | cf08da990c8bf90da116e8db3ac6332cd37578a1 /runtime/ops/spawn.rs | |
parent | 53e974b276b095faf52918c4c6e988e9d2788cef (diff) |
feat: don't require --unstable flag for npm programs (#16520)
This PR adds copies of several unstable APIs that are available
in "Deno[Deno.internal].nodeUnstable" namespace.
These copies do not perform unstable check (ie. don't require
"--unstable" flag to be present). Otherwise they work exactly
the same, including permission checks.
These APIs are not meant to be used by users directly and
can change at any time.
Copies of following APIs are available in that namespace:
- Deno.spawnChild
- Deno.spawn
- Deno.spawnSync
- Deno.serve
- Deno.upgradeHttpRaw
- Deno.listenDatagram
Diffstat (limited to 'runtime/ops/spawn.rs')
-rw-r--r-- | runtime/ops/spawn.rs | 120 |
1 files changed, 114 insertions, 6 deletions
diff --git a/runtime/ops/spawn.rs b/runtime/ops/spawn.rs index 7fe77302a..03ab7d5c2 100644 --- a/runtime/ops/spawn.rs +++ b/runtime/ops/spawn.rs @@ -31,8 +31,10 @@ pub fn init() -> Extension { Extension::builder() .ops(vec![ op_spawn_child::decl(), + op_node_unstable_spawn_child::decl(), op_spawn_wait::decl(), op_spawn_sync::decl(), + op_node_unstable_spawn_sync::decl(), ]) .build() } @@ -123,6 +125,70 @@ pub struct SpawnOutput { stderr: Option<ZeroCopyBuf>, } +fn node_unstable_create_command( + state: &mut OpState, + args: SpawnArgs, + api_name: &str, +) -> Result<std::process::Command, AnyError> { + state + .borrow_mut::<Permissions>() + .run + .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 { + command.current_dir(cwd); + } + + if args.clear_env { + command.env_clear(); + } + command.envs(args.env); + + #[cfg(unix)] + if let Some(gid) = args.gid { + command.gid(gid); + } + #[cfg(unix)] + if let Some(uid) = args.uid { + command.uid(uid); + } + #[cfg(unix)] + // TODO(bartlomieju): + #[allow(clippy::undocumented_unsafe_blocks)] + unsafe { + command.pre_exec(|| { + libc::setgroups(0, std::ptr::null()); + Ok(()) + }); + } + + command.stdin(args.stdio.stdin.as_stdio()); + command.stdout(match args.stdio.stdout { + Stdio::Inherit => StdioOrRid::Rid(1).as_stdio(state)?, + value => value.as_stdio(), + }); + command.stderr(match args.stdio.stderr { + Stdio::Inherit => StdioOrRid::Rid(2).as_stdio(state)?, + value => value.as_stdio(), + }); + + Ok(command) +} + fn create_command( state: &mut OpState, args: SpawnArgs, @@ -200,14 +266,11 @@ struct Child { stderr_rid: Option<ResourceId>, } -#[op] -fn op_spawn_child( +fn spawn_child( state: &mut OpState, - args: SpawnArgs, - api_name: String, + command: std::process::Command, ) -> Result<Child, AnyError> { - let mut command = - tokio::process::Command::from(create_command(state, args, &api_name)?); + let mut command = tokio::process::Command::from(command); // TODO(@crowlkats): allow detaching processes. // currently deno will orphan a process when exiting with an error or Deno.exit() // We want to kill child when it's closed @@ -243,6 +306,26 @@ fn op_spawn_child( } #[op] +fn op_spawn_child( + state: &mut OpState, + args: SpawnArgs, + api_name: String, +) -> Result<Child, AnyError> { + let command = create_command(state, args, &api_name)?; + spawn_child(state, command) +} + +#[op] +fn op_node_unstable_spawn_child( + state: &mut OpState, + args: SpawnArgs, + api_name: String, +) -> Result<Child, AnyError> { + let command = node_unstable_create_command(state, args, &api_name)?; + spawn_child(state, command) +} + +#[op] async fn op_spawn_wait( state: Rc<RefCell<OpState>>, rid: ResourceId, @@ -283,3 +366,28 @@ fn op_spawn_sync( }, }) } + +#[op] +fn op_node_unstable_spawn_sync( + state: &mut OpState, + args: SpawnArgs, +) -> Result<SpawnOutput, AnyError> { + let stdout = matches!(args.stdio.stdout, Stdio::Piped); + let stderr = matches!(args.stdio.stderr, Stdio::Piped); + let output = + node_unstable_create_command(state, args, "Deno.spawnSync()")?.output()?; + + Ok(SpawnOutput { + status: output.status.try_into()?, + stdout: if stdout { + Some(output.stdout.into()) + } else { + None + }, + stderr: if stderr { + Some(output.stderr.into()) + } else { + None + }, + }) +} |