diff options
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 + }, + }) +} |