mirror of
https://github.com/denoland/deno.git
synced 2024-11-25 15:29:32 -05:00
feat: Add deno serve
subcommand (#23511)
By default, `deno serve` will assign port 8000 (like `Deno.serve`). Users may choose a different port using `--port`. `deno serve /tmp/file.ts` `server.ts`: ```ts export default { fetch(req) { return new Response("hello world!\n"); }, }; ```
This commit is contained in:
parent
c1bd9503dd
commit
2f8825a935
21 changed files with 484 additions and 14 deletions
|
@ -22,6 +22,7 @@ use log::Level;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
use std::num::NonZeroU16;
|
||||||
use std::num::NonZeroU32;
|
use std::num::NonZeroU32;
|
||||||
use std::num::NonZeroU8;
|
use std::num::NonZeroU8;
|
||||||
use std::num::NonZeroUsize;
|
use std::num::NonZeroUsize;
|
||||||
|
@ -272,6 +273,26 @@ impl RunFlags {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub struct ServeFlags {
|
||||||
|
pub script: String,
|
||||||
|
pub watch: Option<WatchFlagsWithPaths>,
|
||||||
|
pub port: NonZeroU16,
|
||||||
|
pub host: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ServeFlags {
|
||||||
|
#[cfg(test)]
|
||||||
|
pub fn new_default(script: String, port: u16, host: &str) -> Self {
|
||||||
|
Self {
|
||||||
|
script,
|
||||||
|
watch: None,
|
||||||
|
port: NonZeroU16::new(port).unwrap(),
|
||||||
|
host: host.to_owned(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default, Debug, Eq, PartialEq)]
|
#[derive(Clone, Default, Debug, Eq, PartialEq)]
|
||||||
pub struct WatchFlags {
|
pub struct WatchFlags {
|
||||||
pub hmr: bool,
|
pub hmr: bool,
|
||||||
|
@ -366,6 +387,7 @@ pub enum DenoSubcommand {
|
||||||
Lint(LintFlags),
|
Lint(LintFlags),
|
||||||
Repl(ReplFlags),
|
Repl(ReplFlags),
|
||||||
Run(RunFlags),
|
Run(RunFlags),
|
||||||
|
Serve(ServeFlags),
|
||||||
Task(TaskFlags),
|
Task(TaskFlags),
|
||||||
Test(TestFlags),
|
Test(TestFlags),
|
||||||
Types,
|
Types,
|
||||||
|
@ -776,7 +798,7 @@ impl Flags {
|
||||||
use DenoSubcommand::*;
|
use DenoSubcommand::*;
|
||||||
|
|
||||||
match &self.subcommand {
|
match &self.subcommand {
|
||||||
Run(RunFlags { script, .. }) => {
|
Run(RunFlags { script, .. }) | Serve(ServeFlags { script, .. }) => {
|
||||||
let module_specifier = resolve_url_or_path(script, current_dir).ok()?;
|
let module_specifier = resolve_url_or_path(script, current_dir).ok()?;
|
||||||
if module_specifier.scheme() == "file" {
|
if module_specifier.scheme() == "file" {
|
||||||
let p = module_specifier
|
let p = module_specifier
|
||||||
|
@ -1063,6 +1085,7 @@ pub fn flags_from_vec(args: Vec<OsString>) -> clap::error::Result<Flags> {
|
||||||
"lsp" => lsp_parse(&mut flags, &mut m),
|
"lsp" => lsp_parse(&mut flags, &mut m),
|
||||||
"repl" => repl_parse(&mut flags, &mut m),
|
"repl" => repl_parse(&mut flags, &mut m),
|
||||||
"run" => run_parse(&mut flags, &mut m, app)?,
|
"run" => run_parse(&mut flags, &mut m, app)?,
|
||||||
|
"serve" => serve_parse(&mut flags, &mut m, app)?,
|
||||||
"task" => task_parse(&mut flags, &mut m),
|
"task" => task_parse(&mut flags, &mut m),
|
||||||
"test" => test_parse(&mut flags, &mut m),
|
"test" => test_parse(&mut flags, &mut m),
|
||||||
"types" => types_parse(&mut flags, &mut m),
|
"types" => types_parse(&mut flags, &mut m),
|
||||||
|
@ -1198,6 +1221,7 @@ fn clap_root() -> Command {
|
||||||
.global(true),
|
.global(true),
|
||||||
)
|
)
|
||||||
.subcommand(run_subcommand())
|
.subcommand(run_subcommand())
|
||||||
|
.subcommand(serve_subcommand())
|
||||||
.defer(|cmd| {
|
.defer(|cmd| {
|
||||||
cmd
|
cmd
|
||||||
.subcommand(add_subcommand())
|
.subcommand(add_subcommand())
|
||||||
|
@ -2265,6 +2289,59 @@ Specifying the filename '-' to read the file from stdin.
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn serve_host_validator(host: &str) -> Result<String, String> {
|
||||||
|
if Url::parse(&format!("internal://{host}:9999")).is_ok() {
|
||||||
|
Ok(host.to_owned())
|
||||||
|
} else {
|
||||||
|
Err(format!("Bad serve host: {host}"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serve_subcommand() -> Command {
|
||||||
|
runtime_args(Command::new("serve"), true, true)
|
||||||
|
.arg(
|
||||||
|
Arg::new("port")
|
||||||
|
.long("port")
|
||||||
|
.help("The TCP port to serve on, defaulting to 8000.")
|
||||||
|
.value_parser(value_parser!(NonZeroU16)),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("host")
|
||||||
|
.long("host")
|
||||||
|
.help("The TCP address to serve on, defaulting to 0.0.0.0 (all interfaces).")
|
||||||
|
.value_parser(serve_host_validator),
|
||||||
|
)
|
||||||
|
.arg(check_arg(false))
|
||||||
|
.arg(watch_arg(true))
|
||||||
|
.arg(watch_exclude_arg())
|
||||||
|
.arg(hmr_arg(true))
|
||||||
|
.arg(no_clear_screen_arg())
|
||||||
|
.arg(executable_ext_arg())
|
||||||
|
.arg(
|
||||||
|
script_arg()
|
||||||
|
.required_unless_present("v8-flags")
|
||||||
|
.trailing_var_arg(true),
|
||||||
|
)
|
||||||
|
.arg(env_file_arg())
|
||||||
|
.arg(no_code_cache_arg())
|
||||||
|
.about("Run a server")
|
||||||
|
.long_about("Run a server defined in a main module
|
||||||
|
|
||||||
|
The serve command uses the default exports of the main module to determine which
|
||||||
|
servers to start.
|
||||||
|
|
||||||
|
See https://docs.deno.com/runtime/manual/tools/serve for
|
||||||
|
more detailed information.
|
||||||
|
|
||||||
|
Start a server defined in server.ts:
|
||||||
|
|
||||||
|
deno serve server.ts
|
||||||
|
|
||||||
|
Start a server defined in server.ts, watching for changes and running on port 5050:
|
||||||
|
|
||||||
|
deno serve --watch --port 5050 server.ts")
|
||||||
|
}
|
||||||
|
|
||||||
fn task_subcommand() -> Command {
|
fn task_subcommand() -> Command {
|
||||||
Command::new("task")
|
Command::new("task")
|
||||||
.about("Run a task defined in the configuration file")
|
.about("Run a task defined in the configuration file")
|
||||||
|
@ -3863,6 +3940,63 @@ fn run_parse(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn serve_parse(
|
||||||
|
flags: &mut Flags,
|
||||||
|
matches: &mut ArgMatches,
|
||||||
|
app: Command,
|
||||||
|
) -> clap::error::Result<()> {
|
||||||
|
// deno serve implies --allow-net=host:port
|
||||||
|
let port = matches
|
||||||
|
.remove_one::<NonZeroU16>("port")
|
||||||
|
.unwrap_or(NonZeroU16::new(8000).unwrap());
|
||||||
|
let host = matches
|
||||||
|
.remove_one::<String>("host")
|
||||||
|
.unwrap_or_else(|| "0.0.0.0".to_owned());
|
||||||
|
|
||||||
|
runtime_args_parse(flags, matches, true, true);
|
||||||
|
// If the user didn't pass --allow-net, add this port to the network
|
||||||
|
// allowlist. If the host is 0.0.0.0, we add :{port} and allow the same network perms
|
||||||
|
// as if it was passed to --allow-net directly.
|
||||||
|
let allowed = flags_net::parse(vec![if host == "0.0.0.0" {
|
||||||
|
format!(":{port}")
|
||||||
|
} else {
|
||||||
|
format!("{host}:{port}")
|
||||||
|
}])?;
|
||||||
|
match &mut flags.allow_net {
|
||||||
|
None => flags.allow_net = Some(allowed),
|
||||||
|
Some(v) => {
|
||||||
|
if !v.is_empty() {
|
||||||
|
v.extend(allowed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flags.code_cache_enabled = !matches.get_flag("no-code-cache");
|
||||||
|
|
||||||
|
let mut script_arg =
|
||||||
|
matches.remove_many::<String>("script_arg").ok_or_else(|| {
|
||||||
|
let mut app = app;
|
||||||
|
let subcommand = &mut app.find_subcommand_mut("serve").unwrap();
|
||||||
|
subcommand.error(
|
||||||
|
clap::error::ErrorKind::MissingRequiredArgument,
|
||||||
|
"[SCRIPT_ARG] may only be omitted with --v8-flags=--help",
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let script = script_arg.next().unwrap();
|
||||||
|
flags.argv.extend(script_arg);
|
||||||
|
|
||||||
|
ext_arg_parse(flags, matches);
|
||||||
|
|
||||||
|
flags.subcommand = DenoSubcommand::Serve(ServeFlags {
|
||||||
|
script,
|
||||||
|
watch: watch_arg_parse_with_paths(matches),
|
||||||
|
port,
|
||||||
|
host,
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn task_parse(flags: &mut Flags, matches: &mut ArgMatches) {
|
fn task_parse(flags: &mut Flags, matches: &mut ArgMatches) {
|
||||||
flags.config_flag = matches
|
flags.config_flag = matches
|
||||||
.remove_one::<String>("config")
|
.remove_one::<String>("config")
|
||||||
|
@ -4858,7 +4992,7 @@ mod tests {
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Run(RunFlags::new_default(
|
subcommand: DenoSubcommand::Run(RunFlags::new_default(
|
||||||
"script.ts".to_string()
|
"script.ts".to_string(),
|
||||||
)),
|
)),
|
||||||
v8_flags: svec!["--expose-gc", "--gc-stats=1"],
|
v8_flags: svec!["--expose-gc", "--gc-stats=1"],
|
||||||
code_cache_enabled: true,
|
code_cache_enabled: true,
|
||||||
|
@ -4873,6 +5007,115 @@ mod tests {
|
||||||
.contains("[SCRIPT_ARG] may only be omitted with --v8-flags=--help"));
|
.contains("[SCRIPT_ARG] may only be omitted with --v8-flags=--help"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn serve_flags() {
|
||||||
|
let r = flags_from_vec(svec!["deno", "serve", "main.ts"]);
|
||||||
|
assert_eq!(
|
||||||
|
r.unwrap(),
|
||||||
|
Flags {
|
||||||
|
subcommand: DenoSubcommand::Serve(ServeFlags::new_default(
|
||||||
|
"main.ts".to_string(),
|
||||||
|
8000,
|
||||||
|
"0.0.0.0"
|
||||||
|
)),
|
||||||
|
allow_net: Some(vec![
|
||||||
|
"0.0.0.0:8000".to_string(),
|
||||||
|
"127.0.0.1:8000".to_string(),
|
||||||
|
"localhost:8000".to_string()
|
||||||
|
]),
|
||||||
|
code_cache_enabled: true,
|
||||||
|
..Flags::default()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
let r = flags_from_vec(svec!["deno", "serve", "--port", "5000", "main.ts"]);
|
||||||
|
assert_eq!(
|
||||||
|
r.unwrap(),
|
||||||
|
Flags {
|
||||||
|
subcommand: DenoSubcommand::Serve(ServeFlags::new_default(
|
||||||
|
"main.ts".to_string(),
|
||||||
|
5000,
|
||||||
|
"0.0.0.0"
|
||||||
|
)),
|
||||||
|
allow_net: Some(vec![
|
||||||
|
"0.0.0.0:5000".to_string(),
|
||||||
|
"127.0.0.1:5000".to_string(),
|
||||||
|
"localhost:5000".to_string()
|
||||||
|
]),
|
||||||
|
code_cache_enabled: true,
|
||||||
|
..Flags::default()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
let r = flags_from_vec(svec![
|
||||||
|
"deno",
|
||||||
|
"serve",
|
||||||
|
"--port",
|
||||||
|
"5000",
|
||||||
|
"--allow-net=example.com",
|
||||||
|
"main.ts"
|
||||||
|
]);
|
||||||
|
assert_eq!(
|
||||||
|
r.unwrap(),
|
||||||
|
Flags {
|
||||||
|
subcommand: DenoSubcommand::Serve(ServeFlags::new_default(
|
||||||
|
"main.ts".to_string(),
|
||||||
|
5000,
|
||||||
|
"0.0.0.0"
|
||||||
|
)),
|
||||||
|
allow_net: Some(vec![
|
||||||
|
"example.com".to_string(),
|
||||||
|
"0.0.0.0:5000".to_string(),
|
||||||
|
"127.0.0.1:5000".to_string(),
|
||||||
|
"localhost:5000".to_string()
|
||||||
|
]),
|
||||||
|
code_cache_enabled: true,
|
||||||
|
..Flags::default()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
let r = flags_from_vec(svec![
|
||||||
|
"deno",
|
||||||
|
"serve",
|
||||||
|
"--port",
|
||||||
|
"5000",
|
||||||
|
"--allow-net",
|
||||||
|
"main.ts"
|
||||||
|
]);
|
||||||
|
assert_eq!(
|
||||||
|
r.unwrap(),
|
||||||
|
Flags {
|
||||||
|
subcommand: DenoSubcommand::Serve(ServeFlags::new_default(
|
||||||
|
"main.ts".to_string(),
|
||||||
|
5000,
|
||||||
|
"0.0.0.0"
|
||||||
|
)),
|
||||||
|
allow_net: Some(vec![]),
|
||||||
|
code_cache_enabled: true,
|
||||||
|
..Flags::default()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
let r = flags_from_vec(svec![
|
||||||
|
"deno",
|
||||||
|
"serve",
|
||||||
|
"--port",
|
||||||
|
"5000",
|
||||||
|
"--host",
|
||||||
|
"example.com",
|
||||||
|
"main.ts"
|
||||||
|
]);
|
||||||
|
assert_eq!(
|
||||||
|
r.unwrap(),
|
||||||
|
Flags {
|
||||||
|
subcommand: DenoSubcommand::Serve(ServeFlags::new_default(
|
||||||
|
"main.ts".to_string(),
|
||||||
|
5000,
|
||||||
|
"example.com"
|
||||||
|
)),
|
||||||
|
allow_net: Some(vec!["example.com:5000".to_owned()]),
|
||||||
|
code_cache_enabled: true,
|
||||||
|
..Flags::default()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn has_permission() {
|
fn has_permission() {
|
||||||
let r = flags_from_vec(svec!["deno", "run", "--allow-read", "x.ts"]);
|
let r = flags_from_vec(svec!["deno", "run", "--allow-read", "x.ts"]);
|
||||||
|
|
|
@ -61,6 +61,7 @@ use std::env;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
use std::num::NonZeroU16;
|
||||||
use std::num::NonZeroUsize;
|
use std::num::NonZeroUsize;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
@ -1022,6 +1023,22 @@ impl CliOptions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn serve_port(&self) -> Option<NonZeroU16> {
|
||||||
|
if let DenoSubcommand::Serve(flags) = self.sub_command() {
|
||||||
|
Some(flags.port)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn serve_host(&self) -> Option<String> {
|
||||||
|
if let DenoSubcommand::Serve(flags) = self.sub_command() {
|
||||||
|
Some(flags.host.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn enable_future_features(&self) -> bool {
|
pub fn enable_future_features(&self) -> bool {
|
||||||
*DENO_FUTURE
|
*DENO_FUTURE
|
||||||
}
|
}
|
||||||
|
@ -1062,6 +1079,10 @@ impl CliOptions {
|
||||||
.map_err(AnyError::from)
|
.map_err(AnyError::from)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DenoSubcommand::Serve(run_flags) => {
|
||||||
|
resolve_url_or_path(&run_flags.script, self.initial_cwd())
|
||||||
|
.map_err(AnyError::from)
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
bail!("No main module.")
|
bail!("No main module.")
|
||||||
}
|
}
|
||||||
|
|
|
@ -219,6 +219,7 @@ impl CliFactory {
|
||||||
// Warm up the caches we know we'll likely need based on the CLI mode
|
// Warm up the caches we know we'll likely need based on the CLI mode
|
||||||
match self.options.sub_command() {
|
match self.options.sub_command() {
|
||||||
DenoSubcommand::Run(_)
|
DenoSubcommand::Run(_)
|
||||||
|
| DenoSubcommand::Serve(_)
|
||||||
| DenoSubcommand::Bench(_)
|
| DenoSubcommand::Bench(_)
|
||||||
| DenoSubcommand::Test(_)
|
| DenoSubcommand::Test(_)
|
||||||
| DenoSubcommand::Check(_) => {
|
| DenoSubcommand::Check(_) => {
|
||||||
|
@ -816,6 +817,8 @@ impl CliFactory {
|
||||||
self.feature_checker().clone(),
|
self.feature_checker().clone(),
|
||||||
self.create_cli_main_worker_options()?,
|
self.create_cli_main_worker_options()?,
|
||||||
self.options.node_ipc_fd(),
|
self.options.node_ipc_fd(),
|
||||||
|
self.options.serve_port(),
|
||||||
|
self.options.serve_host(),
|
||||||
self.options.enable_future_features(),
|
self.options.enable_future_features(),
|
||||||
// TODO(bartlomieju): temporarily disabled
|
// TODO(bartlomieju): temporarily disabled
|
||||||
// self.options.disable_deprecated_api_warning,
|
// self.options.disable_deprecated_api_warning,
|
||||||
|
|
|
@ -33,6 +33,7 @@ use crate::util::display;
|
||||||
use crate::util::v8::get_v8_flags_from_env;
|
use crate::util::v8::get_v8_flags_from_env;
|
||||||
use crate::util::v8::init_v8_flags;
|
use crate::util::v8::init_v8_flags;
|
||||||
|
|
||||||
|
use deno_runtime::WorkerExecutionMode;
|
||||||
pub use deno_runtime::UNSTABLE_GRANULAR_FLAGS;
|
pub use deno_runtime::UNSTABLE_GRANULAR_FLAGS;
|
||||||
|
|
||||||
use deno_core::anyhow::Context;
|
use deno_core::anyhow::Context;
|
||||||
|
@ -174,9 +175,12 @@ async fn run_subcommand(flags: Flags) -> Result<i32, AnyError> {
|
||||||
if run_flags.is_stdin() {
|
if run_flags.is_stdin() {
|
||||||
tools::run::run_from_stdin(flags).await
|
tools::run::run_from_stdin(flags).await
|
||||||
} else {
|
} else {
|
||||||
tools::run::run_script(flags, run_flags).await
|
tools::run::run_script(WorkerExecutionMode::Run, flags, run_flags.watch).await
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
DenoSubcommand::Serve(serve_flags) => spawn_subcommand(async move {
|
||||||
|
tools::run::run_script(WorkerExecutionMode::Serve, flags, serve_flags.watch).await
|
||||||
|
}),
|
||||||
DenoSubcommand::Task(task_flags) => spawn_subcommand(async {
|
DenoSubcommand::Task(task_flags) => spawn_subcommand(async {
|
||||||
tools::task::execute_script(flags, task_flags).await
|
tools::task::execute_script(flags, task_flags).await
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -50,6 +50,7 @@ use deno_runtime::deno_tls::rustls::RootCertStore;
|
||||||
use deno_runtime::deno_tls::RootCertStoreProvider;
|
use deno_runtime::deno_tls::RootCertStoreProvider;
|
||||||
use deno_runtime::permissions::Permissions;
|
use deno_runtime::permissions::Permissions;
|
||||||
use deno_runtime::permissions::PermissionsContainer;
|
use deno_runtime::permissions::PermissionsContainer;
|
||||||
|
use deno_runtime::WorkerExecutionMode;
|
||||||
use deno_runtime::WorkerLogLevel;
|
use deno_runtime::WorkerLogLevel;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
use import_map::parse_from_json;
|
use import_map::parse_from_json;
|
||||||
|
@ -567,6 +568,8 @@ pub async fn run(
|
||||||
create_coverage_collector: None,
|
create_coverage_collector: None,
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
false,
|
false,
|
||||||
// TODO(bartlomieju): temporarily disabled
|
// TODO(bartlomieju): temporarily disabled
|
||||||
// metadata.disable_deprecated_api_warning,
|
// metadata.disable_deprecated_api_warning,
|
||||||
|
@ -581,7 +584,11 @@ pub async fn run(
|
||||||
deno_core::JsRuntime::init_platform(None);
|
deno_core::JsRuntime::init_platform(None);
|
||||||
|
|
||||||
let mut worker = worker_factory
|
let mut worker = worker_factory
|
||||||
.create_main_worker(main_module.clone(), permissions)
|
.create_main_worker(
|
||||||
|
WorkerExecutionMode::Run,
|
||||||
|
main_module.clone(),
|
||||||
|
permissions,
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let exit_code = worker.run().await?;
|
let exit_code = worker.run().await?;
|
||||||
|
|
|
@ -35,6 +35,7 @@ use deno_core::PollEventLoopOptions;
|
||||||
use deno_runtime::permissions::Permissions;
|
use deno_runtime::permissions::Permissions;
|
||||||
use deno_runtime::permissions::PermissionsContainer;
|
use deno_runtime::permissions::PermissionsContainer;
|
||||||
use deno_runtime::tokio_util::create_and_run_current_thread;
|
use deno_runtime::tokio_util::create_and_run_current_thread;
|
||||||
|
use deno_runtime::WorkerExecutionMode;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use indexmap::IndexSet;
|
use indexmap::IndexSet;
|
||||||
use log::Level;
|
use log::Level;
|
||||||
|
@ -204,6 +205,7 @@ async fn bench_specifier_inner(
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
let mut worker = worker_factory
|
let mut worker = worker_factory
|
||||||
.create_custom_worker(
|
.create_custom_worker(
|
||||||
|
WorkerExecutionMode::Bench,
|
||||||
specifier.clone(),
|
specifier.clone(),
|
||||||
PermissionsContainer::new(permissions),
|
PermissionsContainer::new(permissions),
|
||||||
vec![ops::bench::deno_bench::init_ops(sender.clone())],
|
vec![ops::bench::deno_bench::init_ops(sender.clone())],
|
||||||
|
|
|
@ -22,6 +22,7 @@ use deno_runtime::deno_io::Stdio;
|
||||||
use deno_runtime::deno_io::StdioPipe;
|
use deno_runtime::deno_io::StdioPipe;
|
||||||
use deno_runtime::permissions::Permissions;
|
use deno_runtime::permissions::Permissions;
|
||||||
use deno_runtime::permissions::PermissionsContainer;
|
use deno_runtime::permissions::PermissionsContainer;
|
||||||
|
use deno_runtime::WorkerExecutionMode;
|
||||||
use deno_terminal::colors;
|
use deno_terminal::colors;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use tokio::sync::mpsc::UnboundedSender;
|
use tokio::sync::mpsc::UnboundedSender;
|
||||||
|
@ -88,6 +89,7 @@ pub async fn kernel(
|
||||||
|
|
||||||
let mut worker = worker_factory
|
let mut worker = worker_factory
|
||||||
.create_custom_worker(
|
.create_custom_worker(
|
||||||
|
WorkerExecutionMode::Jupyter,
|
||||||
main_module.clone(),
|
main_module.clone(),
|
||||||
permissions,
|
permissions,
|
||||||
vec![
|
vec![
|
||||||
|
|
|
@ -15,6 +15,7 @@ use deno_core::serde_json;
|
||||||
use deno_core::unsync::spawn_blocking;
|
use deno_core::unsync::spawn_blocking;
|
||||||
use deno_runtime::permissions::Permissions;
|
use deno_runtime::permissions::Permissions;
|
||||||
use deno_runtime::permissions::PermissionsContainer;
|
use deno_runtime::permissions::PermissionsContainer;
|
||||||
|
use deno_runtime::WorkerExecutionMode;
|
||||||
use rustyline::error::ReadlineError;
|
use rustyline::error::ReadlineError;
|
||||||
|
|
||||||
mod channel;
|
mod channel;
|
||||||
|
@ -170,6 +171,7 @@ pub async fn run(flags: Flags, repl_flags: ReplFlags) -> Result<i32, AnyError> {
|
||||||
let test_event_sender = worker.sender;
|
let test_event_sender = worker.sender;
|
||||||
let mut worker = worker_factory
|
let mut worker = worker_factory
|
||||||
.create_custom_worker(
|
.create_custom_worker(
|
||||||
|
WorkerExecutionMode::Repl,
|
||||||
main_module.clone(),
|
main_module.clone(),
|
||||||
permissions,
|
permissions,
|
||||||
vec![crate::ops::testing::deno_test::init_ops(test_event_sender)],
|
vec![crate::ops::testing::deno_test::init_ops(test_event_sender)],
|
||||||
|
|
|
@ -5,10 +5,10 @@ use std::io::Read;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_runtime::permissions::Permissions;
|
use deno_runtime::permissions::Permissions;
|
||||||
use deno_runtime::permissions::PermissionsContainer;
|
use deno_runtime::permissions::PermissionsContainer;
|
||||||
|
use deno_runtime::WorkerExecutionMode;
|
||||||
|
|
||||||
use crate::args::EvalFlags;
|
use crate::args::EvalFlags;
|
||||||
use crate::args::Flags;
|
use crate::args::Flags;
|
||||||
use crate::args::RunFlags;
|
|
||||||
use crate::args::WatchFlagsWithPaths;
|
use crate::args::WatchFlagsWithPaths;
|
||||||
use crate::factory::CliFactory;
|
use crate::factory::CliFactory;
|
||||||
use crate::factory::CliFactoryBuilder;
|
use crate::factory::CliFactoryBuilder;
|
||||||
|
@ -19,8 +19,9 @@ use crate::util::file_watcher::WatcherRestartMode;
|
||||||
pub mod hmr;
|
pub mod hmr;
|
||||||
|
|
||||||
pub async fn run_script(
|
pub async fn run_script(
|
||||||
|
mode: WorkerExecutionMode,
|
||||||
flags: Flags,
|
flags: Flags,
|
||||||
run_flags: RunFlags,
|
watch: Option<WatchFlagsWithPaths>,
|
||||||
) -> Result<i32, AnyError> {
|
) -> Result<i32, AnyError> {
|
||||||
if !flags.has_permission() && flags.has_permission_in_argv() {
|
if !flags.has_permission() && flags.has_permission_in_argv() {
|
||||||
log::warn!(
|
log::warn!(
|
||||||
|
@ -33,8 +34,8 @@ To grant permissions, set them before the script argument. For example:
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(watch_flags) = run_flags.watch {
|
if let Some(watch_flags) = watch {
|
||||||
return run_with_watch(flags, watch_flags).await;
|
return run_with_watch(mode, flags, watch_flags).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(bartlomieju): actually I think it will also fail if there's an import
|
// TODO(bartlomieju): actually I think it will also fail if there's an import
|
||||||
|
@ -68,7 +69,7 @@ To grant permissions, set them before the script argument. For example:
|
||||||
)?);
|
)?);
|
||||||
let worker_factory = factory.create_cli_main_worker_factory().await?;
|
let worker_factory = factory.create_cli_main_worker_factory().await?;
|
||||||
let mut worker = worker_factory
|
let mut worker = worker_factory
|
||||||
.create_main_worker(main_module, permissions)
|
.create_main_worker(mode, main_module, permissions)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let exit_code = worker.run().await?;
|
let exit_code = worker.run().await?;
|
||||||
|
@ -98,7 +99,7 @@ pub async fn run_from_stdin(flags: Flags) -> Result<i32, AnyError> {
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut worker = worker_factory
|
let mut worker = worker_factory
|
||||||
.create_main_worker(main_module, permissions)
|
.create_main_worker(WorkerExecutionMode::Run, main_module, permissions)
|
||||||
.await?;
|
.await?;
|
||||||
let exit_code = worker.run().await?;
|
let exit_code = worker.run().await?;
|
||||||
Ok(exit_code)
|
Ok(exit_code)
|
||||||
|
@ -107,6 +108,7 @@ pub async fn run_from_stdin(flags: Flags) -> Result<i32, AnyError> {
|
||||||
// TODO(bartlomieju): this function is not handling `exit_code` set by the runtime
|
// TODO(bartlomieju): this function is not handling `exit_code` set by the runtime
|
||||||
// code properly.
|
// code properly.
|
||||||
async fn run_with_watch(
|
async fn run_with_watch(
|
||||||
|
mode: WorkerExecutionMode,
|
||||||
flags: Flags,
|
flags: Flags,
|
||||||
watch_flags: WatchFlagsWithPaths,
|
watch_flags: WatchFlagsWithPaths,
|
||||||
) -> Result<i32, AnyError> {
|
) -> Result<i32, AnyError> {
|
||||||
|
@ -135,7 +137,7 @@ async fn run_with_watch(
|
||||||
let mut worker = factory
|
let mut worker = factory
|
||||||
.create_cli_main_worker_factory()
|
.create_cli_main_worker_factory()
|
||||||
.await?
|
.await?
|
||||||
.create_main_worker(main_module, permissions)
|
.create_main_worker(mode, main_module, permissions)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if watch_flags.hmr {
|
if watch_flags.hmr {
|
||||||
|
@ -184,7 +186,7 @@ pub async fn eval_command(
|
||||||
)?);
|
)?);
|
||||||
let worker_factory = factory.create_cli_main_worker_factory().await?;
|
let worker_factory = factory.create_cli_main_worker_factory().await?;
|
||||||
let mut worker = worker_factory
|
let mut worker = worker_factory
|
||||||
.create_main_worker(main_module, permissions)
|
.create_main_worker(WorkerExecutionMode::Eval, main_module, permissions)
|
||||||
.await?;
|
.await?;
|
||||||
let exit_code = worker.run().await?;
|
let exit_code = worker.run().await?;
|
||||||
Ok(exit_code)
|
Ok(exit_code)
|
||||||
|
|
|
@ -59,6 +59,7 @@ use deno_runtime::permissions::Permissions;
|
||||||
use deno_runtime::permissions::PermissionsContainer;
|
use deno_runtime::permissions::PermissionsContainer;
|
||||||
use deno_runtime::tokio_util::create_and_run_current_thread;
|
use deno_runtime::tokio_util::create_and_run_current_thread;
|
||||||
use deno_runtime::worker::MainWorker;
|
use deno_runtime::worker::MainWorker;
|
||||||
|
use deno_runtime::WorkerExecutionMode;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use indexmap::IndexSet;
|
use indexmap::IndexSet;
|
||||||
use log::Level;
|
use log::Level;
|
||||||
|
@ -583,6 +584,7 @@ async fn configure_main_worker(
|
||||||
) -> Result<(Option<Box<dyn CoverageCollector>>, MainWorker), anyhow::Error> {
|
) -> Result<(Option<Box<dyn CoverageCollector>>, MainWorker), anyhow::Error> {
|
||||||
let mut worker = worker_factory
|
let mut worker = worker_factory
|
||||||
.create_custom_worker(
|
.create_custom_worker(
|
||||||
|
WorkerExecutionMode::Test,
|
||||||
specifier.clone(),
|
specifier.clone(),
|
||||||
PermissionsContainer::new(permissions),
|
PermissionsContainer::new(permissions),
|
||||||
vec![ops::testing::deno_test::init_ops(worker_sender.sender)],
|
vec![ops::testing::deno_test::init_ops(worker_sender.sender)],
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use std::num::NonZeroU16;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -40,6 +41,7 @@ use deno_runtime::web_worker::WebWorkerOptions;
|
||||||
use deno_runtime::worker::MainWorker;
|
use deno_runtime::worker::MainWorker;
|
||||||
use deno_runtime::worker::WorkerOptions;
|
use deno_runtime::worker::WorkerOptions;
|
||||||
use deno_runtime::BootstrapOptions;
|
use deno_runtime::BootstrapOptions;
|
||||||
|
use deno_runtime::WorkerExecutionMode;
|
||||||
use deno_runtime::WorkerLogLevel;
|
use deno_runtime::WorkerLogLevel;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
use deno_semver::package::PackageReqReference;
|
use deno_semver::package::PackageReqReference;
|
||||||
|
@ -142,6 +144,8 @@ struct SharedWorkerState {
|
||||||
disable_deprecated_api_warning: bool,
|
disable_deprecated_api_warning: bool,
|
||||||
verbose_deprecated_api_warning: bool,
|
verbose_deprecated_api_warning: bool,
|
||||||
code_cache: Option<Arc<dyn code_cache::CodeCache>>,
|
code_cache: Option<Arc<dyn code_cache::CodeCache>>,
|
||||||
|
serve_port: Option<NonZeroU16>,
|
||||||
|
serve_host: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SharedWorkerState {
|
impl SharedWorkerState {
|
||||||
|
@ -410,6 +414,8 @@ impl CliMainWorkerFactory {
|
||||||
feature_checker: Arc<FeatureChecker>,
|
feature_checker: Arc<FeatureChecker>,
|
||||||
options: CliMainWorkerOptions,
|
options: CliMainWorkerOptions,
|
||||||
node_ipc: Option<i64>,
|
node_ipc: Option<i64>,
|
||||||
|
serve_port: Option<NonZeroU16>,
|
||||||
|
serve_host: Option<String>,
|
||||||
enable_future_features: bool,
|
enable_future_features: bool,
|
||||||
disable_deprecated_api_warning: bool,
|
disable_deprecated_api_warning: bool,
|
||||||
verbose_deprecated_api_warning: bool,
|
verbose_deprecated_api_warning: bool,
|
||||||
|
@ -434,6 +440,8 @@ impl CliMainWorkerFactory {
|
||||||
maybe_lockfile,
|
maybe_lockfile,
|
||||||
feature_checker,
|
feature_checker,
|
||||||
node_ipc,
|
node_ipc,
|
||||||
|
serve_port,
|
||||||
|
serve_host,
|
||||||
enable_future_features,
|
enable_future_features,
|
||||||
disable_deprecated_api_warning,
|
disable_deprecated_api_warning,
|
||||||
verbose_deprecated_api_warning,
|
verbose_deprecated_api_warning,
|
||||||
|
@ -444,11 +452,13 @@ impl CliMainWorkerFactory {
|
||||||
|
|
||||||
pub async fn create_main_worker(
|
pub async fn create_main_worker(
|
||||||
&self,
|
&self,
|
||||||
|
mode: WorkerExecutionMode,
|
||||||
main_module: ModuleSpecifier,
|
main_module: ModuleSpecifier,
|
||||||
permissions: PermissionsContainer,
|
permissions: PermissionsContainer,
|
||||||
) -> Result<CliMainWorker, AnyError> {
|
) -> Result<CliMainWorker, AnyError> {
|
||||||
self
|
self
|
||||||
.create_custom_worker(
|
.create_custom_worker(
|
||||||
|
mode,
|
||||||
main_module,
|
main_module,
|
||||||
permissions,
|
permissions,
|
||||||
vec![],
|
vec![],
|
||||||
|
@ -459,6 +469,7 @@ impl CliMainWorkerFactory {
|
||||||
|
|
||||||
pub async fn create_custom_worker(
|
pub async fn create_custom_worker(
|
||||||
&self,
|
&self,
|
||||||
|
mode: WorkerExecutionMode,
|
||||||
main_module: ModuleSpecifier,
|
main_module: ModuleSpecifier,
|
||||||
permissions: PermissionsContainer,
|
permissions: PermissionsContainer,
|
||||||
custom_extensions: Vec<Extension>,
|
custom_extensions: Vec<Extension>,
|
||||||
|
@ -545,7 +556,7 @@ impl CliMainWorkerFactory {
|
||||||
let maybe_inspector_server = shared.maybe_inspector_server.clone();
|
let maybe_inspector_server = shared.maybe_inspector_server.clone();
|
||||||
|
|
||||||
let create_web_worker_cb =
|
let create_web_worker_cb =
|
||||||
create_web_worker_callback(shared.clone(), stdio.clone());
|
create_web_worker_callback(mode, shared.clone(), stdio.clone());
|
||||||
|
|
||||||
let maybe_storage_key = shared
|
let maybe_storage_key = shared
|
||||||
.storage_key_resolver
|
.storage_key_resolver
|
||||||
|
@ -600,6 +611,9 @@ impl CliMainWorkerFactory {
|
||||||
disable_deprecated_api_warning: shared.disable_deprecated_api_warning,
|
disable_deprecated_api_warning: shared.disable_deprecated_api_warning,
|
||||||
verbose_deprecated_api_warning: shared.verbose_deprecated_api_warning,
|
verbose_deprecated_api_warning: shared.verbose_deprecated_api_warning,
|
||||||
future: shared.enable_future_features,
|
future: shared.enable_future_features,
|
||||||
|
mode,
|
||||||
|
serve_port: shared.serve_port,
|
||||||
|
serve_host: shared.serve_host.clone(),
|
||||||
},
|
},
|
||||||
extensions: custom_extensions,
|
extensions: custom_extensions,
|
||||||
startup_snapshot: crate::js::deno_isolate_init(),
|
startup_snapshot: crate::js::deno_isolate_init(),
|
||||||
|
@ -745,6 +759,7 @@ impl CliMainWorkerFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_web_worker_callback(
|
fn create_web_worker_callback(
|
||||||
|
mode: WorkerExecutionMode,
|
||||||
shared: Arc<SharedWorkerState>,
|
shared: Arc<SharedWorkerState>,
|
||||||
stdio: deno_runtime::deno_io::Stdio,
|
stdio: deno_runtime::deno_io::Stdio,
|
||||||
) -> Arc<CreateWebWorkerCb> {
|
) -> Arc<CreateWebWorkerCb> {
|
||||||
|
@ -758,7 +773,7 @@ fn create_web_worker_callback(
|
||||||
let maybe_source_map_getter =
|
let maybe_source_map_getter =
|
||||||
shared.module_loader_factory.create_source_map_getter();
|
shared.module_loader_factory.create_source_map_getter();
|
||||||
let create_web_worker_cb =
|
let create_web_worker_cb =
|
||||||
create_web_worker_callback(shared.clone(), stdio.clone());
|
create_web_worker_callback(mode, shared.clone(), stdio.clone());
|
||||||
|
|
||||||
let maybe_storage_key = shared
|
let maybe_storage_key = shared
|
||||||
.storage_key_resolver
|
.storage_key_resolver
|
||||||
|
@ -805,6 +820,9 @@ fn create_web_worker_callback(
|
||||||
disable_deprecated_api_warning: shared.disable_deprecated_api_warning,
|
disable_deprecated_api_warning: shared.disable_deprecated_api_warning,
|
||||||
verbose_deprecated_api_warning: shared.verbose_deprecated_api_warning,
|
verbose_deprecated_api_warning: shared.verbose_deprecated_api_warning,
|
||||||
future: shared.enable_future_features,
|
future: shared.enable_future_features,
|
||||||
|
mode,
|
||||||
|
serve_port: shared.serve_port,
|
||||||
|
serve_host: shared.serve_host.clone(),
|
||||||
},
|
},
|
||||||
extensions: vec![],
|
extensions: vec![],
|
||||||
startup_snapshot: crate::js::deno_isolate_init(),
|
startup_snapshot: crate::js::deno_isolate_init(),
|
||||||
|
|
|
@ -791,8 +791,37 @@ internals.upgradeHttpRaw = upgradeHttpRaw;
|
||||||
internals.serveHttpOnListener = serveHttpOnListener;
|
internals.serveHttpOnListener = serveHttpOnListener;
|
||||||
internals.serveHttpOnConnection = serveHttpOnConnection;
|
internals.serveHttpOnConnection = serveHttpOnConnection;
|
||||||
|
|
||||||
|
function registerDeclarativeServer(exports) {
|
||||||
|
if (ObjectHasOwn(exports, "fetch")) {
|
||||||
|
if (typeof exports.fetch !== "function" || exports.fetch.length !== 1) {
|
||||||
|
throw new TypeError(
|
||||||
|
"Invalid type for fetch: must be a function with a single parameter",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return ({ servePort, serveHost }) => {
|
||||||
|
Deno.serve({
|
||||||
|
port: servePort,
|
||||||
|
hostname: serveHost,
|
||||||
|
onListen: ({ port, hostname }) => {
|
||||||
|
console.debug(
|
||||||
|
`%cdeno serve%c: Listening on %chttp://${hostname}:${port}/%c`,
|
||||||
|
"color: green",
|
||||||
|
"color: inherit",
|
||||||
|
"color: yellow",
|
||||||
|
"color: inherit",
|
||||||
|
);
|
||||||
|
},
|
||||||
|
handler: (req) => {
|
||||||
|
return exports.fetch(req);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
addTrailers,
|
addTrailers,
|
||||||
|
registerDeclarativeServer,
|
||||||
serve,
|
serve,
|
||||||
serveHttpOnConnection,
|
serveHttpOnConnection,
|
||||||
serveHttpOnListener,
|
serveHttpOnListener,
|
||||||
|
|
|
@ -35,6 +35,7 @@ const {
|
||||||
ObjectAssign,
|
ObjectAssign,
|
||||||
ObjectDefineProperties,
|
ObjectDefineProperties,
|
||||||
ObjectDefineProperty,
|
ObjectDefineProperty,
|
||||||
|
ObjectHasOwn,
|
||||||
ObjectKeys,
|
ObjectKeys,
|
||||||
ObjectPrototypeIsPrototypeOf,
|
ObjectPrototypeIsPrototypeOf,
|
||||||
ObjectSetPrototypeOf,
|
ObjectSetPrototypeOf,
|
||||||
|
@ -52,6 +53,7 @@ const {
|
||||||
const {
|
const {
|
||||||
isNativeError,
|
isNativeError,
|
||||||
} = core;
|
} = core;
|
||||||
|
import { registerDeclarativeServer } from "ext:deno_http/00_serve.ts";
|
||||||
import * as event from "ext:deno_web/02_event.js";
|
import * as event from "ext:deno_web/02_event.js";
|
||||||
import * as location from "ext:deno_web/12_location.js";
|
import * as location from "ext:deno_web/12_location.js";
|
||||||
import * as version from "ext:runtime/01_version.ts";
|
import * as version from "ext:runtime/01_version.ts";
|
||||||
|
@ -679,6 +681,18 @@ const {
|
||||||
target,
|
target,
|
||||||
} = op_snapshot_options();
|
} = op_snapshot_options();
|
||||||
|
|
||||||
|
const executionModes = {
|
||||||
|
none: 0,
|
||||||
|
worker: 1,
|
||||||
|
run: 2,
|
||||||
|
repl: 3,
|
||||||
|
eval: 4,
|
||||||
|
test: 5,
|
||||||
|
bench: 6,
|
||||||
|
serve: 7,
|
||||||
|
jupyter: 8,
|
||||||
|
};
|
||||||
|
|
||||||
function bootstrapMainRuntime(runtimeOptions, warmup = false) {
|
function bootstrapMainRuntime(runtimeOptions, warmup = false) {
|
||||||
if (!warmup) {
|
if (!warmup) {
|
||||||
if (hasBootstrapped) {
|
if (hasBootstrapped) {
|
||||||
|
@ -695,8 +709,52 @@ function bootstrapMainRuntime(runtimeOptions, warmup = false) {
|
||||||
7: shouldDisableDeprecatedApiWarning,
|
7: shouldDisableDeprecatedApiWarning,
|
||||||
8: shouldUseVerboseDeprecatedApiWarning,
|
8: shouldUseVerboseDeprecatedApiWarning,
|
||||||
9: future,
|
9: future,
|
||||||
|
10: mode,
|
||||||
|
11: servePort,
|
||||||
|
12: serveHost,
|
||||||
} = runtimeOptions;
|
} = runtimeOptions;
|
||||||
|
|
||||||
|
if (mode === executionModes.run || mode === executionModes.serve) {
|
||||||
|
let serve = undefined;
|
||||||
|
core.addMainModuleHandler((main) => {
|
||||||
|
if (ObjectHasOwn(main, "default")) {
|
||||||
|
try {
|
||||||
|
serve = registerDeclarativeServer(main.default);
|
||||||
|
} catch (e) {
|
||||||
|
if (mode === executionModes.serve) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode === executionModes.serve && !serve) {
|
||||||
|
console.error(
|
||||||
|
`%cerror: %cdeno serve requires %cexport default { fetch }%c in the main module, did you mean to run \"deno run\"?`,
|
||||||
|
"color: yellow;",
|
||||||
|
"color: inherit;",
|
||||||
|
"font-weight: bold;",
|
||||||
|
"font-weight: normal;",
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serve) {
|
||||||
|
if (mode === executionModes.run) {
|
||||||
|
console.error(
|
||||||
|
`%cwarning: %cDetected %cexport default { fetch }%c, did you mean to run \"deno serve\"?`,
|
||||||
|
"color: yellow;",
|
||||||
|
"color: inherit;",
|
||||||
|
"font-weight: bold;",
|
||||||
|
"font-weight: normal;",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (mode === executionModes.serve) {
|
||||||
|
serve({ servePort, serveHost });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(iuioiua): remove in Deno v2. This allows us to dynamically delete
|
// TODO(iuioiua): remove in Deno v2. This allows us to dynamically delete
|
||||||
// class properties within constructors for classes that are not defined
|
// class properties within constructors for classes that are not defined
|
||||||
// within the Deno namespace.
|
// within the Deno namespace.
|
||||||
|
|
|
@ -41,6 +41,7 @@ pub mod worker;
|
||||||
|
|
||||||
mod worker_bootstrap;
|
mod worker_bootstrap;
|
||||||
pub use worker_bootstrap::BootstrapOptions;
|
pub use worker_bootstrap::BootstrapOptions;
|
||||||
|
pub use worker_bootstrap::WorkerExecutionMode;
|
||||||
pub use worker_bootstrap::WorkerLogLevel;
|
pub use worker_bootstrap::WorkerLogLevel;
|
||||||
|
|
||||||
mod shared;
|
mod shared;
|
||||||
|
|
|
@ -4,10 +4,36 @@ use deno_core::v8;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
use std::num::NonZeroU16;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
use deno_terminal::colors;
|
use deno_terminal::colors;
|
||||||
|
|
||||||
|
/// The execution mode for this worker. Some modes may have implicit behaviour.
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum WorkerExecutionMode {
|
||||||
|
/// No special behaviour.
|
||||||
|
None,
|
||||||
|
|
||||||
|
/// Running in a worker.
|
||||||
|
Worker,
|
||||||
|
/// `deno run`
|
||||||
|
Run,
|
||||||
|
/// `deno repl`
|
||||||
|
Repl,
|
||||||
|
/// `deno eval`
|
||||||
|
Eval,
|
||||||
|
/// `deno test`
|
||||||
|
Test,
|
||||||
|
/// `deno bench`
|
||||||
|
Bench,
|
||||||
|
/// `deno serve`
|
||||||
|
Serve,
|
||||||
|
/// `deno jupyter`
|
||||||
|
Jupyter,
|
||||||
|
}
|
||||||
|
|
||||||
/// The log level to use when printing diagnostic log messages, warnings,
|
/// The log level to use when printing diagnostic log messages, warnings,
|
||||||
/// or errors in the worker.
|
/// or errors in the worker.
|
||||||
///
|
///
|
||||||
|
@ -63,6 +89,10 @@ pub struct BootstrapOptions {
|
||||||
pub disable_deprecated_api_warning: bool,
|
pub disable_deprecated_api_warning: bool,
|
||||||
pub verbose_deprecated_api_warning: bool,
|
pub verbose_deprecated_api_warning: bool,
|
||||||
pub future: bool,
|
pub future: bool,
|
||||||
|
pub mode: WorkerExecutionMode,
|
||||||
|
// Used by `deno serve`
|
||||||
|
pub serve_port: Option<NonZeroU16>,
|
||||||
|
pub serve_host: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for BootstrapOptions {
|
impl Default for BootstrapOptions {
|
||||||
|
@ -94,6 +124,9 @@ impl Default for BootstrapOptions {
|
||||||
disable_deprecated_api_warning: false,
|
disable_deprecated_api_warning: false,
|
||||||
verbose_deprecated_api_warning: false,
|
verbose_deprecated_api_warning: false,
|
||||||
future: false,
|
future: false,
|
||||||
|
mode: WorkerExecutionMode::None,
|
||||||
|
serve_port: Default::default(),
|
||||||
|
serve_host: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,6 +162,12 @@ struct BootstrapV8<'a>(
|
||||||
bool,
|
bool,
|
||||||
// future
|
// future
|
||||||
bool,
|
bool,
|
||||||
|
// mode
|
||||||
|
i32,
|
||||||
|
// serve port
|
||||||
|
u16,
|
||||||
|
// serve host
|
||||||
|
Option<&'a str>,
|
||||||
);
|
);
|
||||||
|
|
||||||
impl BootstrapOptions {
|
impl BootstrapOptions {
|
||||||
|
@ -151,6 +190,9 @@ impl BootstrapOptions {
|
||||||
self.disable_deprecated_api_warning,
|
self.disable_deprecated_api_warning,
|
||||||
self.verbose_deprecated_api_warning,
|
self.verbose_deprecated_api_warning,
|
||||||
self.future,
|
self.future,
|
||||||
|
self.mode as u8 as _,
|
||||||
|
self.serve_port.map(|x| x.into()).unwrap_or_default(),
|
||||||
|
self.serve_host.as_deref(),
|
||||||
);
|
);
|
||||||
|
|
||||||
bootstrap.serialize(ser).unwrap()
|
bootstrap.serialize(ser).unwrap()
|
||||||
|
|
5
tests/specs/serve/bad/__test__.jsonc
Normal file
5
tests/specs/serve/bad/__test__.jsonc
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"args": "serve --port 12345 main.ts",
|
||||||
|
"output": "main.out",
|
||||||
|
"tempDir": true
|
||||||
|
}
|
1
tests/specs/serve/bad/main.out
Normal file
1
tests/specs/serve/bad/main.out
Normal file
|
@ -0,0 +1 @@
|
||||||
|
error: deno serve requires export default { fetch } in the main module, did you mean to run "deno run"?
|
4
tests/specs/serve/bad/main.ts
Normal file
4
tests/specs/serve/bad/main.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
export default {
|
||||||
|
bad() {
|
||||||
|
},
|
||||||
|
};
|
5
tests/specs/serve/basic/__test__.jsonc
Normal file
5
tests/specs/serve/basic/__test__.jsonc
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"args": "serve --port 12345 main.ts",
|
||||||
|
"output": "main.out",
|
||||||
|
"tempDir": true
|
||||||
|
}
|
1
tests/specs/serve/basic/main.out
Normal file
1
tests/specs/serve/basic/main.out
Normal file
|
@ -0,0 +1 @@
|
||||||
|
deno serve: Listening on http://localhost:12345/
|
18
tests/specs/serve/basic/main.ts
Normal file
18
tests/specs/serve/basic/main.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
(async () => {
|
||||||
|
for (let i = 0; i < 1000; i++) {
|
||||||
|
try {
|
||||||
|
const resp = await fetch("http://localhost:12345/");
|
||||||
|
Deno.exit(0);
|
||||||
|
} catch {
|
||||||
|
await new Promise((r) => setTimeout(r, 10));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Deno.exit(2);
|
||||||
|
})();
|
||||||
|
|
||||||
|
export default {
|
||||||
|
fetch(req) {
|
||||||
|
return new Response("Hello world!");
|
||||||
|
},
|
||||||
|
};
|
Loading…
Reference in a new issue