mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 17:34:47 -05:00
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
This commit is contained in:
parent
53e974b276
commit
8d5c0112fb
13 changed files with 576 additions and 329 deletions
|
@ -1,7 +1,6 @@
|
||||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
use crate::proc_state::ProcState;
|
use crate::proc_state::ProcState;
|
||||||
use deno_core::anyhow::bail;
|
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::op;
|
use deno_core::op;
|
||||||
use deno_core::Extension;
|
use deno_core::Extension;
|
||||||
|
@ -27,10 +26,5 @@ fn init_proc_state(ps: ProcState) -> Extension {
|
||||||
#[op]
|
#[op]
|
||||||
fn op_npm_process_state(state: &mut OpState) -> Result<String, AnyError> {
|
fn op_npm_process_state(state: &mut OpState) -> Result<String, AnyError> {
|
||||||
let proc_state = state.borrow_mut::<ProcState>();
|
let proc_state = state.borrow_mut::<ProcState>();
|
||||||
if !proc_state.options.unstable() {
|
|
||||||
bail!(
|
|
||||||
"Unstable use of npm process state. The --unstable flag must be provided."
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Ok(proc_state.npm_resolver.get_npm_process_state())
|
Ok(proc_state.npm_resolver.get_npm_process_state())
|
||||||
}
|
}
|
||||||
|
|
|
@ -274,6 +274,7 @@ impl ProcState {
|
||||||
/// module before attempting to `load()` it from a `JsRuntime`. It will
|
/// module before attempting to `load()` it from a `JsRuntime`. It will
|
||||||
/// populate `self.graph_data` in memory with the necessary source code, write
|
/// populate `self.graph_data` in memory with the necessary source code, write
|
||||||
/// emits where necessary or report any module graph / type checking errors.
|
/// emits where necessary or report any module graph / type checking errors.
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub async fn prepare_module_load(
|
pub async fn prepare_module_load(
|
||||||
&self,
|
&self,
|
||||||
roots: Vec<ModuleSpecifier>,
|
roots: Vec<ModuleSpecifier>,
|
||||||
|
|
|
@ -103,7 +103,7 @@ itest!(dual_cjs_esm {
|
||||||
});
|
});
|
||||||
|
|
||||||
itest!(child_process_fork_test {
|
itest!(child_process_fork_test {
|
||||||
args: "run --unstable -A --quiet npm/child_process_fork_test/main.ts",
|
args: "run -A --quiet npm/child_process_fork_test/main.ts",
|
||||||
output: "npm/child_process_fork_test/main.out",
|
output: "npm/child_process_fork_test/main.out",
|
||||||
envs: env_vars(),
|
envs: env_vars(),
|
||||||
http_server: true,
|
http_server: true,
|
||||||
|
@ -621,7 +621,7 @@ itest!(node_modules_dir_with_deps {
|
||||||
});
|
});
|
||||||
|
|
||||||
itest!(node_modules_dir_yargs {
|
itest!(node_modules_dir_yargs {
|
||||||
args: "run --allow-read --allow-env --unstable --node-modules-dir $TESTDATA/npm/cjs_yargs/main.js",
|
args: "run --allow-read --allow-env --node-modules-dir $TESTDATA/npm/cjs_yargs/main.js",
|
||||||
output: "npm/cjs_yargs/main.out",
|
output: "npm/cjs_yargs/main.out",
|
||||||
envs: env_vars(),
|
envs: env_vars(),
|
||||||
http_server: true,
|
http_server: true,
|
||||||
|
@ -1050,7 +1050,6 @@ fn peer_deps_with_copied_folders_and_lockfile() {
|
||||||
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
||||||
.current_dir(temp_dir.path())
|
.current_dir(temp_dir.path())
|
||||||
.arg("run")
|
.arg("run")
|
||||||
.arg("--unstable")
|
|
||||||
.arg("-A")
|
.arg("-A")
|
||||||
.arg("main.ts")
|
.arg("main.ts")
|
||||||
.envs(env_vars())
|
.envs(env_vars())
|
||||||
|
@ -1082,7 +1081,6 @@ fn peer_deps_with_copied_folders_and_lockfile() {
|
||||||
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
||||||
.current_dir(temp_dir.path())
|
.current_dir(temp_dir.path())
|
||||||
.arg("run")
|
.arg("run")
|
||||||
.arg("--unstable")
|
|
||||||
.arg("-A")
|
.arg("-A")
|
||||||
.arg("main.ts")
|
.arg("main.ts")
|
||||||
.envs(env_vars())
|
.envs(env_vars())
|
||||||
|
@ -1097,7 +1095,6 @@ fn peer_deps_with_copied_folders_and_lockfile() {
|
||||||
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
||||||
.current_dir(temp_dir.path())
|
.current_dir(temp_dir.path())
|
||||||
.arg("run")
|
.arg("run")
|
||||||
.arg("--unstable")
|
|
||||||
.arg("--reload")
|
.arg("--reload")
|
||||||
.arg("-A")
|
.arg("-A")
|
||||||
.arg("main.ts")
|
.arg("main.ts")
|
||||||
|
@ -1114,7 +1111,6 @@ fn peer_deps_with_copied_folders_and_lockfile() {
|
||||||
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
||||||
.current_dir(temp_dir.path())
|
.current_dir(temp_dir.path())
|
||||||
.arg("run")
|
.arg("run")
|
||||||
.arg("--unstable")
|
|
||||||
.arg("--node-modules-dir")
|
.arg("--node-modules-dir")
|
||||||
.arg("-A")
|
.arg("-A")
|
||||||
.arg("main.ts")
|
.arg("main.ts")
|
||||||
|
@ -1139,7 +1135,6 @@ fn peer_deps_with_copied_folders_and_lockfile() {
|
||||||
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
||||||
.current_dir(temp_dir.path())
|
.current_dir(temp_dir.path())
|
||||||
.arg("run")
|
.arg("run")
|
||||||
.arg("--unstable")
|
|
||||||
.arg("--node-modules-dir")
|
.arg("--node-modules-dir")
|
||||||
.arg("-A")
|
.arg("-A")
|
||||||
.arg("main.ts")
|
.arg("main.ts")
|
||||||
|
@ -1156,7 +1151,6 @@ fn peer_deps_with_copied_folders_and_lockfile() {
|
||||||
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
||||||
.current_dir(temp_dir.path())
|
.current_dir(temp_dir.path())
|
||||||
.arg("run")
|
.arg("run")
|
||||||
.arg("--unstable")
|
|
||||||
.arg("--node-modules-dir")
|
.arg("--node-modules-dir")
|
||||||
.arg("--reload")
|
.arg("--reload")
|
||||||
.arg("-A")
|
.arg("-A")
|
||||||
|
@ -1174,7 +1168,6 @@ fn peer_deps_with_copied_folders_and_lockfile() {
|
||||||
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
||||||
.current_dir(temp_dir.path())
|
.current_dir(temp_dir.path())
|
||||||
.arg("run")
|
.arg("run")
|
||||||
.arg("--unstable")
|
|
||||||
.arg("--node-modules-dir")
|
.arg("--node-modules-dir")
|
||||||
.arg("--no-lock")
|
.arg("--no-lock")
|
||||||
.arg("--reload")
|
.arg("--reload")
|
||||||
|
|
|
@ -422,7 +422,8 @@
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function serve(arg1, arg2) {
|
function createServe(opFn) {
|
||||||
|
return async function serve(arg1, arg2) {
|
||||||
let options = undefined;
|
let options = undefined;
|
||||||
let handler = undefined;
|
let handler = undefined;
|
||||||
if (arg1 instanceof Function) {
|
if (arg1 instanceof Function) {
|
||||||
|
@ -479,7 +480,7 @@
|
||||||
listenOpts.key = options.key;
|
listenOpts.key = options.key;
|
||||||
}
|
}
|
||||||
|
|
||||||
const serverId = core.ops.op_flash_serve(listenOpts);
|
const serverId = opFn(listenOpts);
|
||||||
const serverPromise = core.opAsync("op_flash_drive_server", serverId);
|
const serverPromise = core.opAsync("op_flash_drive_server", serverId);
|
||||||
|
|
||||||
PromisePrototypeCatch(
|
PromisePrototypeCatch(
|
||||||
|
@ -655,6 +656,7 @@
|
||||||
PromisePrototypeCatch(server.serve(), console.error),
|
PromisePrototypeCatch(server.serve(), console.error),
|
||||||
serverPromise,
|
serverPromise,
|
||||||
]);
|
]);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function createRequestBodyStream(serverId, token) {
|
function createRequestBodyStream(serverId, token) {
|
||||||
|
@ -722,7 +724,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
window.__bootstrap.flash = {
|
window.__bootstrap.flash = {
|
||||||
serve,
|
createServe,
|
||||||
upgradeHttpRaw,
|
upgradeHttpRaw,
|
||||||
};
|
};
|
||||||
})(this);
|
})(this);
|
||||||
|
|
|
@ -1171,15 +1171,13 @@ pub fn resolve_addr_sync(
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op]
|
fn flash_serve<P>(
|
||||||
fn op_flash_serve<P>(
|
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
opts: ListenOpts,
|
opts: ListenOpts,
|
||||||
) -> Result<u32, AnyError>
|
) -> Result<u32, AnyError>
|
||||||
where
|
where
|
||||||
P: FlashPermissions + 'static,
|
P: FlashPermissions + 'static,
|
||||||
{
|
{
|
||||||
check_unstable(state, "Deno.serve");
|
|
||||||
state
|
state
|
||||||
.borrow_mut::<P>()
|
.borrow_mut::<P>()
|
||||||
.check_net(&(&opts.hostname, Some(opts.port)), "Deno.serve()")?;
|
.check_net(&(&opts.hostname, Some(opts.port)), "Deno.serve()")?;
|
||||||
|
@ -1223,6 +1221,29 @@ where
|
||||||
Ok(server_id)
|
Ok(server_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[op]
|
||||||
|
fn op_flash_serve<P>(
|
||||||
|
state: &mut OpState,
|
||||||
|
opts: ListenOpts,
|
||||||
|
) -> Result<u32, AnyError>
|
||||||
|
where
|
||||||
|
P: FlashPermissions + 'static,
|
||||||
|
{
|
||||||
|
check_unstable(state, "Deno.serve");
|
||||||
|
flash_serve::<P>(state, opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[op]
|
||||||
|
fn op_node_unstable_flash_serve<P>(
|
||||||
|
state: &mut OpState,
|
||||||
|
opts: ListenOpts,
|
||||||
|
) -> Result<u32, AnyError>
|
||||||
|
where
|
||||||
|
P: FlashPermissions + 'static,
|
||||||
|
{
|
||||||
|
flash_serve::<P>(state, opts)
|
||||||
|
}
|
||||||
|
|
||||||
#[op]
|
#[op]
|
||||||
fn op_flash_wait_for_listening(
|
fn op_flash_wait_for_listening(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
|
@ -1445,6 +1466,7 @@ pub fn init<P: FlashPermissions + 'static>(unstable: bool) -> Extension {
|
||||||
))
|
))
|
||||||
.ops(vec![
|
.ops(vec![
|
||||||
op_flash_serve::decl::<P>(),
|
op_flash_serve::decl::<P>(),
|
||||||
|
op_node_unstable_flash_serve::decl::<P>(),
|
||||||
op_flash_respond::decl(),
|
op_flash_respond::decl(),
|
||||||
op_flash_respond_async::decl(),
|
op_flash_respond_async::decl(),
|
||||||
op_flash_respond_chuncked::decl(),
|
op_flash_respond_chuncked::decl(),
|
||||||
|
|
|
@ -319,10 +319,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function listenDatagram(args) {
|
function createListenDatagram(udpOpFn, unixOpFn) {
|
||||||
|
return function listenDatagram(args) {
|
||||||
switch (args.transport) {
|
switch (args.transport) {
|
||||||
case "udp": {
|
case "udp": {
|
||||||
const [rid, addr] = ops.op_net_listen_udp(
|
const [rid, addr] = udpOpFn(
|
||||||
{
|
{
|
||||||
hostname: args.hostname ?? "127.0.0.1",
|
hostname: args.hostname ?? "127.0.0.1",
|
||||||
port: args.port,
|
port: args.port,
|
||||||
|
@ -333,7 +334,7 @@
|
||||||
return new Datagram(rid, addr);
|
return new Datagram(rid, addr);
|
||||||
}
|
}
|
||||||
case "unixpacket": {
|
case "unixpacket": {
|
||||||
const [rid, path] = ops.op_net_listen_unixpacket(args.path);
|
const [rid, path] = unixOpFn(args.path);
|
||||||
const addr = {
|
const addr = {
|
||||||
transport: "unixpacket",
|
transport: "unixpacket",
|
||||||
path,
|
path,
|
||||||
|
@ -343,6 +344,7 @@
|
||||||
default:
|
default:
|
||||||
throw new TypeError(`Unsupported transport: '${transport}'`);
|
throw new TypeError(`Unsupported transport: '${transport}'`);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function connect(args) {
|
async function connect(args) {
|
||||||
|
@ -389,7 +391,7 @@
|
||||||
TcpConn,
|
TcpConn,
|
||||||
UnixConn,
|
UnixConn,
|
||||||
listen,
|
listen,
|
||||||
listenDatagram,
|
createListenDatagram,
|
||||||
Listener,
|
Listener,
|
||||||
shutdown,
|
shutdown,
|
||||||
Datagram,
|
Datagram,
|
||||||
|
|
|
@ -53,10 +53,13 @@ pub fn init<P: NetPermissions + 'static>() -> Vec<OpDecl> {
|
||||||
crate::ops_unix::op_net_connect_unix::decl::<P>(),
|
crate::ops_unix::op_net_connect_unix::decl::<P>(),
|
||||||
op_net_listen_tcp::decl::<P>(),
|
op_net_listen_tcp::decl::<P>(),
|
||||||
op_net_listen_udp::decl::<P>(),
|
op_net_listen_udp::decl::<P>(),
|
||||||
|
op_node_unstable_net_listen_udp::decl::<P>(),
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
crate::ops_unix::op_net_listen_unix::decl::<P>(),
|
crate::ops_unix::op_net_listen_unix::decl::<P>(),
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
crate::ops_unix::op_net_listen_unixpacket::decl::<P>(),
|
crate::ops_unix::op_net_listen_unixpacket::decl::<P>(),
|
||||||
|
#[cfg(unix)]
|
||||||
|
crate::ops_unix::op_node_unstable_net_listen_unixpacket::decl::<P>(),
|
||||||
op_net_recv_udp::decl(),
|
op_net_recv_udp::decl(),
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
crate::ops_unix::op_net_recv_unixpacket::decl(),
|
crate::ops_unix::op_net_recv_unixpacket::decl(),
|
||||||
|
@ -288,8 +291,7 @@ where
|
||||||
Ok((rid, IpAddr::from(local_addr)))
|
Ok((rid, IpAddr::from(local_addr)))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op]
|
fn net_listen_udp<NP>(
|
||||||
fn op_net_listen_udp<NP>(
|
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
addr: IpAddr,
|
addr: IpAddr,
|
||||||
reuse_address: bool,
|
reuse_address: bool,
|
||||||
|
@ -297,7 +299,6 @@ fn op_net_listen_udp<NP>(
|
||||||
where
|
where
|
||||||
NP: NetPermissions + 'static,
|
NP: NetPermissions + 'static,
|
||||||
{
|
{
|
||||||
super::check_unstable(state, "Deno.listenDatagram");
|
|
||||||
state
|
state
|
||||||
.borrow_mut::<NP>()
|
.borrow_mut::<NP>()
|
||||||
.check_net(&(&addr.hostname, Some(addr.port)), "Deno.listenDatagram()")?;
|
.check_net(&(&addr.hostname, Some(addr.port)), "Deno.listenDatagram()")?;
|
||||||
|
@ -343,6 +344,32 @@ where
|
||||||
Ok((rid, IpAddr::from(local_addr)))
|
Ok((rid, IpAddr::from(local_addr)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[op]
|
||||||
|
fn op_net_listen_udp<NP>(
|
||||||
|
state: &mut OpState,
|
||||||
|
addr: IpAddr,
|
||||||
|
reuse_address: bool,
|
||||||
|
) -> Result<(ResourceId, IpAddr), AnyError>
|
||||||
|
where
|
||||||
|
NP: NetPermissions + 'static,
|
||||||
|
{
|
||||||
|
super::check_unstable(state, "Deno.listenDatagram");
|
||||||
|
net_listen_udp::<NP>(state, addr, reuse_address)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[op]
|
||||||
|
fn op_node_unstable_net_listen_udp<NP>(
|
||||||
|
state: &mut OpState,
|
||||||
|
addr: IpAddr,
|
||||||
|
reuse_address: bool,
|
||||||
|
) -> Result<(ResourceId, IpAddr), AnyError>
|
||||||
|
where
|
||||||
|
NP: NetPermissions + 'static,
|
||||||
|
{
|
||||||
|
super::check_unstable(state, "Deno.listenDatagram");
|
||||||
|
net_listen_udp::<NP>(state, addr, reuse_address)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Eq, PartialEq, Debug)]
|
#[derive(Serialize, Eq, PartialEq, Debug)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
pub enum DnsReturnRecord {
|
pub enum DnsReturnRecord {
|
||||||
|
|
|
@ -209,8 +209,7 @@ where
|
||||||
Ok((rid, pathname))
|
Ok((rid, pathname))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op]
|
pub fn net_listen_unixpacket<NP>(
|
||||||
pub fn op_net_listen_unixpacket<NP>(
|
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
path: String,
|
path: String,
|
||||||
) -> Result<(ResourceId, Option<String>), AnyError>
|
) -> Result<(ResourceId, Option<String>), AnyError>
|
||||||
|
@ -218,7 +217,6 @@ where
|
||||||
NP: NetPermissions + 'static,
|
NP: NetPermissions + 'static,
|
||||||
{
|
{
|
||||||
let address_path = Path::new(&path);
|
let address_path = Path::new(&path);
|
||||||
super::check_unstable(state, "Deno.listenDatagram");
|
|
||||||
let permissions = state.borrow_mut::<NP>();
|
let permissions = state.borrow_mut::<NP>();
|
||||||
permissions.check_read(address_path, "Deno.listenDatagram()")?;
|
permissions.check_read(address_path, "Deno.listenDatagram()")?;
|
||||||
permissions.check_write(address_path, "Deno.listenDatagram()")?;
|
permissions.check_write(address_path, "Deno.listenDatagram()")?;
|
||||||
|
@ -233,6 +231,29 @@ where
|
||||||
Ok((rid, pathname))
|
Ok((rid, pathname))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[op]
|
||||||
|
pub fn op_net_listen_unixpacket<NP>(
|
||||||
|
state: &mut OpState,
|
||||||
|
path: String,
|
||||||
|
) -> Result<(ResourceId, Option<String>), AnyError>
|
||||||
|
where
|
||||||
|
NP: NetPermissions + 'static,
|
||||||
|
{
|
||||||
|
super::check_unstable(state, "Deno.listenDatagram");
|
||||||
|
net_listen_unixpacket::<NP>(state, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[op]
|
||||||
|
pub fn op_node_unstable_net_listen_unixpacket<NP>(
|
||||||
|
state: &mut OpState,
|
||||||
|
path: String,
|
||||||
|
) -> Result<(ResourceId, Option<String>), AnyError>
|
||||||
|
where
|
||||||
|
NP: NetPermissions + 'static,
|
||||||
|
{
|
||||||
|
net_listen_unixpacket::<NP>(state, path)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pathstring(pathname: &Path) -> Result<String, AnyError> {
|
pub fn pathstring(pathname: &Path) -> Result<String, AnyError> {
|
||||||
into_string(pathname.into())
|
into_string(pathname.into())
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
const promiseIdSymbol = SymbolFor("Deno.core.internalPromiseId");
|
const promiseIdSymbol = SymbolFor("Deno.core.internalPromiseId");
|
||||||
|
|
||||||
function spawnChildInner(command, apiName, {
|
function spawnChildInner(opFn, command, apiName, {
|
||||||
args = [],
|
args = [],
|
||||||
cwd = undefined,
|
cwd = undefined,
|
||||||
clearEnv = false,
|
clearEnv = false,
|
||||||
|
@ -39,7 +39,7 @@
|
||||||
signal = undefined,
|
signal = undefined,
|
||||||
windowsRawArguments = false,
|
windowsRawArguments = false,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
const child = ops.op_spawn_child({
|
const child = opFn({
|
||||||
cmd: pathFromURL(command),
|
cmd: pathFromURL(command),
|
||||||
args: ArrayPrototypeMap(args, String),
|
args: ArrayPrototypeMap(args, String),
|
||||||
cwd: pathFromURL(cwd),
|
cwd: pathFromURL(cwd),
|
||||||
|
@ -58,8 +58,10 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function spawnChild(command, options = {}) {
|
function createSpawnChild(opFn) {
|
||||||
return spawnChildInner(command, "Deno.spawnChild()", options);
|
return function spawnChild(command, options = {}) {
|
||||||
|
return spawnChildInner(opFn, command, "Deno.spawnChild()", options);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function collectOutput(readableStream) {
|
async function collectOutput(readableStream) {
|
||||||
|
@ -227,16 +229,19 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function spawn(command, options) {
|
function createSpawn(opFn) {
|
||||||
|
return function spawn(command, options) {
|
||||||
if (options?.stdin === "piped") {
|
if (options?.stdin === "piped") {
|
||||||
throw new TypeError(
|
throw new TypeError(
|
||||||
"Piped stdin is not supported for this function, use 'Deno.spawnChild()' instead",
|
"Piped stdin is not supported for this function, use 'Deno.spawnChild()' instead",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return spawnChildInner(command, "Deno.spawn()", options).output();
|
return spawnChildInner(opFn, command, "Deno.spawn()", options).output();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function spawnSync(command, {
|
function createSpawnSync(opFn) {
|
||||||
|
return function spawnSync(command, {
|
||||||
args = [],
|
args = [],
|
||||||
cwd = undefined,
|
cwd = undefined,
|
||||||
clearEnv = false,
|
clearEnv = false,
|
||||||
|
@ -253,7 +258,7 @@
|
||||||
"Piped stdin is not supported for this function, use 'Deno.spawnChild()' instead",
|
"Piped stdin is not supported for this function, use 'Deno.spawnChild()' instead",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const result = ops.op_spawn_sync({
|
const result = opFn({
|
||||||
cmd: pathFromURL(command),
|
cmd: pathFromURL(command),
|
||||||
args: ArrayPrototypeMap(args, String),
|
args: ArrayPrototypeMap(args, String),
|
||||||
cwd: pathFromURL(cwd),
|
cwd: pathFromURL(cwd),
|
||||||
|
@ -283,12 +288,13 @@
|
||||||
return result.stderr;
|
return result.stderr;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
window.__bootstrap.spawn = {
|
window.__bootstrap.spawn = {
|
||||||
Child,
|
Child,
|
||||||
spawnChild,
|
createSpawn,
|
||||||
spawn,
|
createSpawnChild,
|
||||||
spawnSync,
|
createSpawnSync,
|
||||||
};
|
};
|
||||||
})(this);
|
})(this);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
((window) => {
|
((window) => {
|
||||||
const core = window.Deno.core;
|
const core = window.Deno.core;
|
||||||
const __bootstrap = window.__bootstrap;
|
const __bootstrap = window.__bootstrap;
|
||||||
|
|
||||||
__bootstrap.denoNs = {
|
__bootstrap.denoNs = {
|
||||||
metrics: core.metrics,
|
metrics: core.metrics,
|
||||||
test: __bootstrap.testing.test,
|
test: __bootstrap.testing.test,
|
||||||
|
|
|
@ -700,6 +700,7 @@ delete Intl.v8BreakIterator;
|
||||||
const wrapConsole = window.__bootstrap.console.wrapConsole;
|
const wrapConsole = window.__bootstrap.console.wrapConsole;
|
||||||
|
|
||||||
// Remove bootstrapping data from the global scope
|
// Remove bootstrapping data from the global scope
|
||||||
|
const __bootstrap = globalThis.__bootstrap;
|
||||||
delete globalThis.__bootstrap;
|
delete globalThis.__bootstrap;
|
||||||
delete globalThis.bootstrap;
|
delete globalThis.bootstrap;
|
||||||
util.log("bootstrapMainRuntime");
|
util.log("bootstrapMainRuntime");
|
||||||
|
@ -755,6 +756,27 @@ delete Intl.v8BreakIterator;
|
||||||
|
|
||||||
const internalSymbol = Symbol("Deno.internal");
|
const internalSymbol = Symbol("Deno.internal");
|
||||||
|
|
||||||
|
// These have to initialized here and not in `90_deno_ns.js` because
|
||||||
|
// the op function that needs to be passed will be invalidated by creating
|
||||||
|
// a snapshot
|
||||||
|
ObjectAssign(internals, {
|
||||||
|
nodeUnstable: {
|
||||||
|
spawnChild: __bootstrap.spawn.createSpawnChild(
|
||||||
|
ops.op_node_unstable_spawn_child,
|
||||||
|
),
|
||||||
|
spawn: __bootstrap.spawn.createSpawn(ops.op_node_unstable_spawn_child),
|
||||||
|
spawnSync: __bootstrap.spawn.createSpawnSync(
|
||||||
|
ops.op_node_unstable_spawn_sync,
|
||||||
|
),
|
||||||
|
serve: __bootstrap.flash.createServe(ops.op_node_unstable_flash_serve),
|
||||||
|
upgradeHttpRaw: __bootstrap.flash.upgradeHttpRaw,
|
||||||
|
listenDatagram: __bootstrap.net.createListenDatagram(
|
||||||
|
ops.op_node_unstable_net_listen_udp,
|
||||||
|
ops.op_node_unstable_net_listen_unixpacket,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const finalDenoNs = {
|
const finalDenoNs = {
|
||||||
core,
|
core,
|
||||||
internal: internalSymbol,
|
internal: internalSymbol,
|
||||||
|
@ -773,6 +795,19 @@ delete Intl.v8BreakIterator;
|
||||||
|
|
||||||
if (runtimeOptions.unstableFlag) {
|
if (runtimeOptions.unstableFlag) {
|
||||||
ObjectAssign(finalDenoNs, denoNsUnstable);
|
ObjectAssign(finalDenoNs, denoNsUnstable);
|
||||||
|
// These have to initialized here and not in `90_deno_ns.js` because
|
||||||
|
// the op function that needs to be passed will be invalidated by creating
|
||||||
|
// a snapshot
|
||||||
|
ObjectAssign(finalDenoNs, {
|
||||||
|
spawnChild: __bootstrap.spawn.createSpawnChild(ops.op_spawn_child),
|
||||||
|
spawn: __bootstrap.spawn.createSpawn(ops.op_spawn_child),
|
||||||
|
spawnSync: __bootstrap.spawn.createSpawnSync(ops.op_spawn_sync),
|
||||||
|
serve: __bootstrap.flash.createServe(ops.op_flash_serve),
|
||||||
|
listenDatagram: __bootstrap.net.createListenDatagram(
|
||||||
|
ops.op_net_listen_udp,
|
||||||
|
ops.op_net_listen_unixpacket,
|
||||||
|
),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup `Deno` global - we're actually overriding already existing global
|
// Setup `Deno` global - we're actually overriding already existing global
|
||||||
|
@ -800,6 +835,7 @@ delete Intl.v8BreakIterator;
|
||||||
const wrapConsole = window.__bootstrap.console.wrapConsole;
|
const wrapConsole = window.__bootstrap.console.wrapConsole;
|
||||||
|
|
||||||
// Remove bootstrapping data from the global scope
|
// Remove bootstrapping data from the global scope
|
||||||
|
const __bootstrap = globalThis.__bootstrap;
|
||||||
delete globalThis.__bootstrap;
|
delete globalThis.__bootstrap;
|
||||||
delete globalThis.bootstrap;
|
delete globalThis.bootstrap;
|
||||||
util.log("bootstrapWorkerRuntime");
|
util.log("bootstrapWorkerRuntime");
|
||||||
|
@ -849,6 +885,27 @@ delete Intl.v8BreakIterator;
|
||||||
|
|
||||||
const internalSymbol = Symbol("Deno.internal");
|
const internalSymbol = Symbol("Deno.internal");
|
||||||
|
|
||||||
|
// These have to initialized here and not in `90_deno_ns.js` because
|
||||||
|
// the op function that needs to be passed will be invalidated by creating
|
||||||
|
// a snapshot
|
||||||
|
ObjectAssign(internals, {
|
||||||
|
nodeUnstable: {
|
||||||
|
spawnChild: __bootstrap.spawn.createSpawnChild(
|
||||||
|
ops.op_node_unstable_spawn_child,
|
||||||
|
),
|
||||||
|
spawn: __bootstrap.spawn.createSpawn(ops.op_node_unstable_spawn_child),
|
||||||
|
spawnSync: __bootstrap.spawn.createSpawnSync(
|
||||||
|
ops.op_node_unstable_spawn_sync,
|
||||||
|
),
|
||||||
|
serve: __bootstrap.flash.createServe(ops.op_node_unstable_flash_serve),
|
||||||
|
upgradeHttpRaw: __bootstrap.flash.upgradeHttpRaw,
|
||||||
|
listenDatagram: __bootstrap.net.createListenDatagram(
|
||||||
|
ops.op_node_unstable_net_listen_udp,
|
||||||
|
ops.op_node_unstable_net_listen_unixpacket,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const finalDenoNs = {
|
const finalDenoNs = {
|
||||||
core,
|
core,
|
||||||
internal: internalSymbol,
|
internal: internalSymbol,
|
||||||
|
@ -859,6 +916,19 @@ delete Intl.v8BreakIterator;
|
||||||
};
|
};
|
||||||
if (runtimeOptions.unstableFlag) {
|
if (runtimeOptions.unstableFlag) {
|
||||||
ObjectAssign(finalDenoNs, denoNsUnstable);
|
ObjectAssign(finalDenoNs, denoNsUnstable);
|
||||||
|
// These have to initialized here and not in `90_deno_ns.js` because
|
||||||
|
// the op function that needs to be passed will be invalidated by creating
|
||||||
|
// a snapshot
|
||||||
|
ObjectAssign(finalDenoNs, {
|
||||||
|
spawnChild: __bootstrap.spawn.createSpawnChild(ops.op_spawn_child),
|
||||||
|
spawn: __bootstrap.spawn.createSpawn(ops.op_spawn_child),
|
||||||
|
spawnSync: __bootstrap.spawn.createSpawnSync(ops.op_spawn_sync),
|
||||||
|
serve: __bootstrap.flash.createServe(ops.op_flash_serve),
|
||||||
|
listenDatagram: __bootstrap.net.createListenDatagram(
|
||||||
|
ops.op_net_listen_udp,
|
||||||
|
ops.op_net_listen_unixpacket,
|
||||||
|
),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
ObjectDefineProperties(finalDenoNs, {
|
ObjectDefineProperties(finalDenoNs, {
|
||||||
pid: util.readOnly(runtimeOptions.pid),
|
pid: util.readOnly(runtimeOptions.pid),
|
||||||
|
|
|
@ -31,8 +31,10 @@ pub fn init() -> Extension {
|
||||||
Extension::builder()
|
Extension::builder()
|
||||||
.ops(vec![
|
.ops(vec![
|
||||||
op_spawn_child::decl(),
|
op_spawn_child::decl(),
|
||||||
|
op_node_unstable_spawn_child::decl(),
|
||||||
op_spawn_wait::decl(),
|
op_spawn_wait::decl(),
|
||||||
op_spawn_sync::decl(),
|
op_spawn_sync::decl(),
|
||||||
|
op_node_unstable_spawn_sync::decl(),
|
||||||
])
|
])
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
@ -123,6 +125,70 @@ pub struct SpawnOutput {
|
||||||
stderr: Option<ZeroCopyBuf>,
|
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(
|
fn create_command(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
args: SpawnArgs,
|
args: SpawnArgs,
|
||||||
|
@ -200,14 +266,11 @@ struct Child {
|
||||||
stderr_rid: Option<ResourceId>,
|
stderr_rid: Option<ResourceId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op]
|
fn spawn_child(
|
||||||
fn op_spawn_child(
|
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
args: SpawnArgs,
|
command: std::process::Command,
|
||||||
api_name: String,
|
|
||||||
) -> Result<Child, AnyError> {
|
) -> Result<Child, AnyError> {
|
||||||
let mut command =
|
let mut command = tokio::process::Command::from(command);
|
||||||
tokio::process::Command::from(create_command(state, args, &api_name)?);
|
|
||||||
// TODO(@crowlkats): allow detaching processes.
|
// TODO(@crowlkats): allow detaching processes.
|
||||||
// currently deno will orphan a process when exiting with an error or Deno.exit()
|
// currently deno will orphan a process when exiting with an error or Deno.exit()
|
||||||
// We want to kill child when it's closed
|
// We want to kill child when it's closed
|
||||||
|
@ -242,6 +305,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]
|
#[op]
|
||||||
async fn op_spawn_wait(
|
async fn op_spawn_wait(
|
||||||
state: Rc<RefCell<OpState>>,
|
state: Rc<RefCell<OpState>>,
|
||||||
|
@ -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
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 241e7eb8f91a06e75d8e7108b1b35ca202adf92f
|
Subproject commit c56a8c4e3245dd9ea1a892d2f2150ddba57f29c3
|
Loading…
Add table
Reference in a new issue