mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 17:34:47 -05:00
feat(cli/standalone): support runtime flags for deno compile (#8738)
This commit is contained in:
parent
444eca80a9
commit
cbc2108525
16 changed files with 428 additions and 127 deletions
|
@ -283,14 +283,14 @@ impl FileFetcher {
|
||||||
http_cache: HttpCache,
|
http_cache: HttpCache,
|
||||||
cache_setting: CacheSetting,
|
cache_setting: CacheSetting,
|
||||||
allow_remote: bool,
|
allow_remote: bool,
|
||||||
maybe_ca_data: Option<&str>,
|
ca_data: Option<Vec<u8>>,
|
||||||
) -> Result<Self, AnyError> {
|
) -> Result<Self, AnyError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
allow_remote,
|
allow_remote,
|
||||||
cache: FileCache::default(),
|
cache: FileCache::default(),
|
||||||
cache_setting,
|
cache_setting,
|
||||||
http_cache,
|
http_cache,
|
||||||
http_client: create_http_client(get_user_agent(), maybe_ca_data)?,
|
http_client: create_http_client(get_user_agent(), ca_data)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
146
cli/flags.rs
146
cli/flags.rs
|
@ -6,14 +6,20 @@ use clap::Arg;
|
||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
use clap::ArgSettings;
|
use clap::ArgSettings;
|
||||||
use clap::SubCommand;
|
use clap::SubCommand;
|
||||||
|
use deno_core::serde::de;
|
||||||
|
use deno_core::serde::Deserialize;
|
||||||
|
use deno_core::serde::Deserializer;
|
||||||
|
use deno_core::serde::Serialize;
|
||||||
|
use deno_core::serde::Serializer;
|
||||||
use deno_runtime::permissions::PermissionsOptions;
|
use deno_runtime::permissions::PermissionsOptions;
|
||||||
use log::Level;
|
use log::Level;
|
||||||
|
use std::fmt;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use tempfile::TempDir;
|
use tempfile::TempDir;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
|
||||||
pub enum DenoSubcommand {
|
pub enum DenoSubcommand {
|
||||||
Bundle {
|
Bundle {
|
||||||
source_file: String,
|
source_file: String,
|
||||||
|
@ -25,6 +31,7 @@ pub enum DenoSubcommand {
|
||||||
Compile {
|
Compile {
|
||||||
source_file: String,
|
source_file: String,
|
||||||
output: Option<PathBuf>,
|
output: Option<PathBuf>,
|
||||||
|
args: Vec<String>,
|
||||||
},
|
},
|
||||||
Completions {
|
Completions {
|
||||||
buf: Box<[u8]>,
|
buf: Box<[u8]>,
|
||||||
|
@ -92,7 +99,66 @@ impl Default for DenoSubcommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Default)]
|
fn deserialize_maybe_log_level<'de, D>(d: D) -> Result<Option<Level>, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
struct OptionalLogLevelVisitor;
|
||||||
|
impl<'de> de::Visitor<'de> for OptionalLogLevelVisitor {
|
||||||
|
type Value = Option<Level>;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(formatter, "null or a valid log level string")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_none<E>(self) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_some<D>(self, d: D) -> Result<Self::Value, D::Error>
|
||||||
|
where
|
||||||
|
D: de::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
struct LogLevelVisitor;
|
||||||
|
impl<'de> de::Visitor<'de> for LogLevelVisitor {
|
||||||
|
type Value = Level;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(formatter, "a valid log level string")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
Level::from_str(s).map_err(|_| {
|
||||||
|
de::Error::invalid_value(de::Unexpected::Str(s), &self)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(Some(d.deserialize_str(LogLevelVisitor)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d.deserialize_option(OptionalLogLevelVisitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_maybe_log_level<S>(
|
||||||
|
maybe_level: &Option<Level>,
|
||||||
|
s: S,
|
||||||
|
) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
match maybe_level {
|
||||||
|
None => s.serialize_none(),
|
||||||
|
Some(level) => s.serialize_str(&level.to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize)]
|
||||||
pub struct Flags {
|
pub struct Flags {
|
||||||
/// Vector of CLI arguments - these are user script arguments, all Deno
|
/// Vector of CLI arguments - these are user script arguments, all Deno
|
||||||
/// specific flags are removed.
|
/// specific flags are removed.
|
||||||
|
@ -117,6 +183,8 @@ pub struct Flags {
|
||||||
pub inspect_brk: Option<SocketAddr>,
|
pub inspect_brk: Option<SocketAddr>,
|
||||||
pub lock: Option<PathBuf>,
|
pub lock: Option<PathBuf>,
|
||||||
pub lock_write: bool,
|
pub lock_write: bool,
|
||||||
|
#[serde(deserialize_with = "deserialize_maybe_log_level")]
|
||||||
|
#[serde(serialize_with = "serialize_maybe_log_level")]
|
||||||
pub log_level: Option<Level>,
|
pub log_level: Option<Level>,
|
||||||
pub no_check: bool,
|
pub no_check: bool,
|
||||||
pub no_prompts: bool,
|
pub no_prompts: bool,
|
||||||
|
@ -407,7 +475,7 @@ fn fmt_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn install_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
fn install_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
runtime_args_parse(flags, matches, true);
|
runtime_args_parse(flags, matches, true, true);
|
||||||
|
|
||||||
let root = if matches.is_present("root") {
|
let root = if matches.is_present("root") {
|
||||||
let install_root = matches.value_of("root").unwrap();
|
let install_root = matches.value_of("root").unwrap();
|
||||||
|
@ -437,14 +505,22 @@ fn install_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
fn compile_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
compile_args_parse(flags, matches);
|
runtime_args_parse(flags, matches, true, false);
|
||||||
|
|
||||||
let source_file = matches.value_of("source_file").unwrap().to_string();
|
let mut script: Vec<String> = matches
|
||||||
|
.values_of("script_arg")
|
||||||
|
.unwrap()
|
||||||
|
.map(String::from)
|
||||||
|
.collect();
|
||||||
|
assert!(!script.is_empty());
|
||||||
|
let args = script.split_off(1);
|
||||||
|
let source_file = script[0].to_string();
|
||||||
let output = matches.value_of("output").map(PathBuf::from);
|
let output = matches.value_of("output").map(PathBuf::from);
|
||||||
|
|
||||||
flags.subcommand = DenoSubcommand::Compile {
|
flags.subcommand = DenoSubcommand::Compile {
|
||||||
source_file,
|
source_file,
|
||||||
output,
|
output,
|
||||||
|
args,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,7 +559,7 @@ fn completions_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn repl_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
fn repl_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
runtime_args_parse(flags, matches, false);
|
runtime_args_parse(flags, matches, false, true);
|
||||||
flags.repl = true;
|
flags.repl = true;
|
||||||
flags.subcommand = DenoSubcommand::Repl;
|
flags.subcommand = DenoSubcommand::Repl;
|
||||||
flags.allow_net = Some(vec![]);
|
flags.allow_net = Some(vec![]);
|
||||||
|
@ -496,7 +572,7 @@ fn repl_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
fn eval_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
runtime_args_parse(flags, matches, false);
|
runtime_args_parse(flags, matches, false, true);
|
||||||
flags.allow_net = Some(vec![]);
|
flags.allow_net = Some(vec![]);
|
||||||
flags.allow_env = true;
|
flags.allow_env = true;
|
||||||
flags.allow_run = true;
|
flags.allow_run = true;
|
||||||
|
@ -577,13 +653,22 @@ fn compile_args_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
ca_file_arg_parse(flags, matches);
|
ca_file_arg_parse(flags, matches);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn runtime_args<'a, 'b>(app: App<'a, 'b>, include_perms: bool) -> App<'a, 'b> {
|
fn runtime_args<'a, 'b>(
|
||||||
let app = inspect_args(compile_args(app));
|
app: App<'a, 'b>,
|
||||||
|
include_perms: bool,
|
||||||
|
include_inspector: bool,
|
||||||
|
) -> App<'a, 'b> {
|
||||||
|
let app = compile_args(app);
|
||||||
let app = if include_perms {
|
let app = if include_perms {
|
||||||
permission_args(app)
|
permission_args(app)
|
||||||
} else {
|
} else {
|
||||||
app
|
app
|
||||||
};
|
};
|
||||||
|
let app = if include_inspector {
|
||||||
|
inspect_args(app)
|
||||||
|
} else {
|
||||||
|
app
|
||||||
|
};
|
||||||
app
|
app
|
||||||
.arg(cached_only_arg())
|
.arg(cached_only_arg())
|
||||||
.arg(v8_flags_arg())
|
.arg(v8_flags_arg())
|
||||||
|
@ -594,19 +679,22 @@ fn runtime_args_parse(
|
||||||
flags: &mut Flags,
|
flags: &mut Flags,
|
||||||
matches: &clap::ArgMatches,
|
matches: &clap::ArgMatches,
|
||||||
include_perms: bool,
|
include_perms: bool,
|
||||||
|
include_inspector: bool,
|
||||||
) {
|
) {
|
||||||
compile_args_parse(flags, matches);
|
compile_args_parse(flags, matches);
|
||||||
cached_only_arg_parse(flags, matches);
|
cached_only_arg_parse(flags, matches);
|
||||||
if include_perms {
|
if include_perms {
|
||||||
permission_args_parse(flags, matches);
|
permission_args_parse(flags, matches);
|
||||||
}
|
}
|
||||||
|
if include_inspector {
|
||||||
|
inspect_arg_parse(flags, matches);
|
||||||
|
}
|
||||||
v8_flags_arg_parse(flags, matches);
|
v8_flags_arg_parse(flags, matches);
|
||||||
seed_arg_parse(flags, matches);
|
seed_arg_parse(flags, matches);
|
||||||
inspect_arg_parse(flags, matches);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
fn run_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
runtime_args_parse(flags, matches, true);
|
runtime_args_parse(flags, matches, true, true);
|
||||||
|
|
||||||
let mut script: Vec<String> = matches
|
let mut script: Vec<String> = matches
|
||||||
.values_of("script_arg")
|
.values_of("script_arg")
|
||||||
|
@ -625,7 +713,7 @@ fn run_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
fn test_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
runtime_args_parse(flags, matches, true);
|
runtime_args_parse(flags, matches, true, true);
|
||||||
|
|
||||||
let no_run = matches.is_present("no-run");
|
let no_run = matches.is_present("no-run");
|
||||||
let fail_fast = matches.is_present("fail-fast");
|
let fail_fast = matches.is_present("fail-fast");
|
||||||
|
@ -799,12 +887,12 @@ Ignore formatting a file by adding an ignore comment at the top of the file:
|
||||||
}
|
}
|
||||||
|
|
||||||
fn repl_subcommand<'a, 'b>() -> App<'a, 'b> {
|
fn repl_subcommand<'a, 'b>() -> App<'a, 'b> {
|
||||||
runtime_args(SubCommand::with_name("repl"), false)
|
runtime_args(SubCommand::with_name("repl"), false, true)
|
||||||
.about("Read Eval Print Loop")
|
.about("Read Eval Print Loop")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn install_subcommand<'a, 'b>() -> App<'a, 'b> {
|
fn install_subcommand<'a, 'b>() -> App<'a, 'b> {
|
||||||
runtime_args(SubCommand::with_name("install"), true)
|
runtime_args(SubCommand::with_name("install"), true, true)
|
||||||
.setting(AppSettings::TrailingVarArg)
|
.setting(AppSettings::TrailingVarArg)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("cmd")
|
Arg::with_name("cmd")
|
||||||
|
@ -859,11 +947,10 @@ These must be added to the path manually if required.")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_subcommand<'a, 'b>() -> App<'a, 'b> {
|
fn compile_subcommand<'a, 'b>() -> App<'a, 'b> {
|
||||||
compile_args(SubCommand::with_name("compile"))
|
runtime_args(SubCommand::with_name("compile"), true, false)
|
||||||
|
.setting(AppSettings::TrailingVarArg)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("source_file")
|
script_arg(),
|
||||||
.takes_value(true)
|
|
||||||
.required(true),
|
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("output")
|
Arg::with_name("output")
|
||||||
|
@ -878,6 +965,10 @@ fn compile_subcommand<'a, 'b>() -> App<'a, 'b> {
|
||||||
deno compile --unstable https://deno.land/std/http/file_server.ts
|
deno compile --unstable https://deno.land/std/http/file_server.ts
|
||||||
deno compile --unstable --output /usr/local/bin/color_util https://deno.land/std/examples/colors.ts
|
deno compile --unstable --output /usr/local/bin/color_util https://deno.land/std/examples/colors.ts
|
||||||
|
|
||||||
|
Any flags passed which affect runtime behavior, such as '--unstable',
|
||||||
|
'--allow-*', '--v8-flags', etc. are encoded into the output executable and used
|
||||||
|
at runtime as if they were passed to a similar 'deno run' command.
|
||||||
|
|
||||||
The executable name is inferred by default:
|
The executable name is inferred by default:
|
||||||
- Attempt to take the file stem of the URL path. The above example would
|
- Attempt to take the file stem of the URL path. The above example would
|
||||||
become 'file_server'.
|
become 'file_server'.
|
||||||
|
@ -926,7 +1017,7 @@ fn completions_subcommand<'a, 'b>() -> App<'a, 'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_subcommand<'a, 'b>() -> App<'a, 'b> {
|
fn eval_subcommand<'a, 'b>() -> App<'a, 'b> {
|
||||||
runtime_args(SubCommand::with_name("eval"), false)
|
runtime_args(SubCommand::with_name("eval"), false, true)
|
||||||
.about("Eval script")
|
.about("Eval script")
|
||||||
.long_about(
|
.long_about(
|
||||||
"Evaluate JavaScript from the command line.
|
"Evaluate JavaScript from the command line.
|
||||||
|
@ -1246,7 +1337,7 @@ fn permission_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_subcommand<'a, 'b>() -> App<'a, 'b> {
|
fn run_subcommand<'a, 'b>() -> App<'a, 'b> {
|
||||||
runtime_args(SubCommand::with_name("run"), true)
|
runtime_args(SubCommand::with_name("run"), true, true)
|
||||||
.arg(
|
.arg(
|
||||||
watch_arg()
|
watch_arg()
|
||||||
.conflicts_with("inspect")
|
.conflicts_with("inspect")
|
||||||
|
@ -1280,7 +1371,7 @@ Deno allows specifying the filename '-' to read the file from stdin.
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_subcommand<'a, 'b>() -> App<'a, 'b> {
|
fn test_subcommand<'a, 'b>() -> App<'a, 'b> {
|
||||||
runtime_args(SubCommand::with_name("test"), true)
|
runtime_args(SubCommand::with_name("test"), true, true)
|
||||||
.setting(AppSettings::TrailingVarArg)
|
.setting(AppSettings::TrailingVarArg)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("no-run")
|
Arg::with_name("no-run")
|
||||||
|
@ -3306,7 +3397,8 @@ mod tests {
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Compile {
|
subcommand: DenoSubcommand::Compile {
|
||||||
source_file: "https://deno.land/std/examples/colors.ts".to_string(),
|
source_file: "https://deno.land/std/examples/colors.ts".to_string(),
|
||||||
output: None
|
output: None,
|
||||||
|
args: vec![],
|
||||||
},
|
},
|
||||||
..Flags::default()
|
..Flags::default()
|
||||||
}
|
}
|
||||||
|
@ -3316,13 +3408,14 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn compile_with_flags() {
|
fn compile_with_flags() {
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
let r = flags_from_vec_safe(svec!["deno", "compile", "--unstable", "--import-map", "import_map.json", "--no-remote", "--config", "tsconfig.json", "--no-check", "--reload", "--lock", "lock.json", "--lock-write", "--cert", "example.crt", "--output", "colors", "https://deno.land/std/examples/colors.ts"]);
|
let r = flags_from_vec_safe(svec!["deno", "compile", "--unstable", "--import-map", "import_map.json", "--no-remote", "--config", "tsconfig.json", "--no-check", "--reload", "--lock", "lock.json", "--lock-write", "--cert", "example.crt", "--cached-only", "--allow-read", "--allow-net", "--v8-flags=--help", "--seed", "1", "--output", "colors", "https://deno.land/std/examples/colors.ts", "foo", "bar"]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Compile {
|
subcommand: DenoSubcommand::Compile {
|
||||||
source_file: "https://deno.land/std/examples/colors.ts".to_string(),
|
source_file: "https://deno.land/std/examples/colors.ts".to_string(),
|
||||||
output: Some(PathBuf::from("colors"))
|
output: Some(PathBuf::from("colors")),
|
||||||
|
args: svec!["foo", "bar"],
|
||||||
},
|
},
|
||||||
unstable: true,
|
unstable: true,
|
||||||
import_map_path: Some("import_map.json".to_string()),
|
import_map_path: Some("import_map.json".to_string()),
|
||||||
|
@ -3333,6 +3426,11 @@ mod tests {
|
||||||
lock: Some(PathBuf::from("lock.json")),
|
lock: Some(PathBuf::from("lock.json")),
|
||||||
lock_write: true,
|
lock_write: true,
|
||||||
ca_file: Some("example.crt".to_string()),
|
ca_file: Some("example.crt".to_string()),
|
||||||
|
cached_only: true,
|
||||||
|
allow_read: Some(vec![]),
|
||||||
|
allow_net: Some(vec![]),
|
||||||
|
v8_flags: svec!["--help", "--random-seed=1"],
|
||||||
|
seed: Some(1),
|
||||||
..Flags::default()
|
..Flags::default()
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -23,7 +23,7 @@ pub fn get_user_agent() -> String {
|
||||||
/// proxies and doesn't follow redirects.
|
/// proxies and doesn't follow redirects.
|
||||||
pub fn create_http_client(
|
pub fn create_http_client(
|
||||||
user_agent: String,
|
user_agent: String,
|
||||||
ca_data: Option<&str>,
|
ca_data: Option<Vec<u8>>,
|
||||||
) -> Result<Client, AnyError> {
|
) -> Result<Client, AnyError> {
|
||||||
let mut headers = HeaderMap::new();
|
let mut headers = HeaderMap::new();
|
||||||
headers.insert(USER_AGENT, user_agent.parse().unwrap());
|
headers.insert(USER_AGENT, user_agent.parse().unwrap());
|
||||||
|
@ -33,8 +33,7 @@ pub fn create_http_client(
|
||||||
.use_rustls_tls();
|
.use_rustls_tls();
|
||||||
|
|
||||||
if let Some(ca_data) = ca_data {
|
if let Some(ca_data) = ca_data {
|
||||||
let ca_data_vec = ca_data.as_bytes().to_vec();
|
let cert = reqwest::Certificate::from_pem(&ca_data)?;
|
||||||
let cert = reqwest::Certificate::from_pem(&ca_data_vec)?;
|
|
||||||
builder = builder.add_root_certificate(cert);
|
builder = builder.add_root_certificate(cert);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,9 +155,9 @@ pub async fn fetch_once(
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::fs::read_to_string;
|
use std::fs::read;
|
||||||
|
|
||||||
fn create_test_client(ca_data: Option<&str>) -> Client {
|
fn create_test_client(ca_data: Option<Vec<u8>>) -> Client {
|
||||||
create_http_client("test_client".to_string(), ca_data).unwrap()
|
create_http_client("test_client".to_string(), ca_data).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,12 +311,20 @@ mod tests {
|
||||||
// Relies on external http server. See target/debug/test_server
|
// Relies on external http server. See target/debug/test_server
|
||||||
let url =
|
let url =
|
||||||
Url::parse("https://localhost:5545/cli/tests/fixture.json").unwrap();
|
Url::parse("https://localhost:5545/cli/tests/fixture.json").unwrap();
|
||||||
let ca_data: String = read_to_string(
|
|
||||||
test_util::root_path().join("std/http/testdata/tls/RootCA.pem"),
|
let client = create_http_client(
|
||||||
|
get_user_agent(),
|
||||||
|
Some(
|
||||||
|
read(
|
||||||
|
test_util::root_path()
|
||||||
|
.join("std/http/testdata/tls/RootCA.pem")
|
||||||
|
.to_str()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let client =
|
|
||||||
create_http_client(get_user_agent(), Some(ca_data.as_str())).unwrap();
|
|
||||||
let result = fetch_once(client, &url, None).await;
|
let result = fetch_once(client, &url, None).await;
|
||||||
if let Ok(FetchOnceResult::Code(body, headers)) = result {
|
if let Ok(FetchOnceResult::Code(body, headers)) = result {
|
||||||
assert!(!body.is_empty());
|
assert!(!body.is_empty());
|
||||||
|
@ -337,12 +344,19 @@ mod tests {
|
||||||
"https://localhost:5545/cli/tests/053_import_compression/gziped",
|
"https://localhost:5545/cli/tests/053_import_compression/gziped",
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let ca_data: String = read_to_string(
|
let client = create_http_client(
|
||||||
test_util::root_path().join("std/http/testdata/tls/RootCA.pem"),
|
get_user_agent(),
|
||||||
|
Some(
|
||||||
|
read(
|
||||||
|
test_util::root_path()
|
||||||
|
.join("std/http/testdata/tls/RootCA.pem")
|
||||||
|
.to_str()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let client =
|
|
||||||
create_http_client(get_user_agent(), Some(ca_data.as_str())).unwrap();
|
|
||||||
let result = fetch_once(client, &url, None).await;
|
let result = fetch_once(client, &url, None).await;
|
||||||
if let Ok(FetchOnceResult::Code(body, headers)) = result {
|
if let Ok(FetchOnceResult::Code(body, headers)) = result {
|
||||||
assert_eq!(String::from_utf8(body).unwrap(), "console.log('gzip')");
|
assert_eq!(String::from_utf8(body).unwrap(), "console.log('gzip')");
|
||||||
|
@ -361,12 +375,19 @@ mod tests {
|
||||||
async fn test_fetch_with_cafile_with_etag() {
|
async fn test_fetch_with_cafile_with_etag() {
|
||||||
let _http_server_guard = test_util::http_server();
|
let _http_server_guard = test_util::http_server();
|
||||||
let url = Url::parse("https://localhost:5545/etag_script.ts").unwrap();
|
let url = Url::parse("https://localhost:5545/etag_script.ts").unwrap();
|
||||||
let ca_data: String = read_to_string(
|
let client = create_http_client(
|
||||||
test_util::root_path().join("std/http/testdata/tls/RootCA.pem"),
|
get_user_agent(),
|
||||||
|
Some(
|
||||||
|
read(
|
||||||
|
test_util::root_path()
|
||||||
|
.join("std/http/testdata/tls/RootCA.pem")
|
||||||
|
.to_str()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let client =
|
|
||||||
create_http_client(get_user_agent(), Some(ca_data.as_str())).unwrap();
|
|
||||||
let result = fetch_once(client.clone(), &url, None).await;
|
let result = fetch_once(client.clone(), &url, None).await;
|
||||||
if let Ok(FetchOnceResult::Code(body, headers)) = result {
|
if let Ok(FetchOnceResult::Code(body, headers)) = result {
|
||||||
assert!(!body.is_empty());
|
assert!(!body.is_empty());
|
||||||
|
@ -394,12 +415,19 @@ mod tests {
|
||||||
"https://localhost:5545/cli/tests/053_import_compression/brotli",
|
"https://localhost:5545/cli/tests/053_import_compression/brotli",
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let ca_data: String = read_to_string(
|
let client = create_http_client(
|
||||||
test_util::root_path().join("std/http/testdata/tls/RootCA.pem"),
|
get_user_agent(),
|
||||||
|
Some(
|
||||||
|
read(
|
||||||
|
test_util::root_path()
|
||||||
|
.join("std/http/testdata/tls/RootCA.pem")
|
||||||
|
.to_str()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let client =
|
|
||||||
create_http_client(get_user_agent(), Some(ca_data.as_str())).unwrap();
|
|
||||||
let result = fetch_once(client, &url, None).await;
|
let result = fetch_once(client, &url, None).await;
|
||||||
if let Ok(FetchOnceResult::Code(body, headers)) = result {
|
if let Ok(FetchOnceResult::Code(body, headers)) = result {
|
||||||
assert!(!body.is_empty());
|
assert!(!body.is_empty());
|
||||||
|
|
14
cli/main.rs
14
cli/main.rs
|
@ -113,7 +113,7 @@ fn create_web_worker_callback(
|
||||||
.log_level
|
.log_level
|
||||||
.map_or(false, |l| l == log::Level::Debug),
|
.map_or(false, |l| l == log::Level::Debug),
|
||||||
unstable: program_state.flags.unstable,
|
unstable: program_state.flags.unstable,
|
||||||
ca_filepath: program_state.flags.ca_file.clone(),
|
ca_data: program_state.ca_data.clone(),
|
||||||
user_agent: http_util::get_user_agent(),
|
user_agent: http_util::get_user_agent(),
|
||||||
seed: program_state.flags.seed,
|
seed: program_state.flags.seed,
|
||||||
module_loader,
|
module_loader,
|
||||||
|
@ -189,7 +189,7 @@ pub fn create_main_worker(
|
||||||
.log_level
|
.log_level
|
||||||
.map_or(false, |l| l == log::Level::Debug),
|
.map_or(false, |l| l == log::Level::Debug),
|
||||||
unstable: program_state.flags.unstable,
|
unstable: program_state.flags.unstable,
|
||||||
ca_filepath: program_state.flags.ca_file.clone(),
|
ca_data: program_state.ca_data.clone(),
|
||||||
user_agent: http_util::get_user_agent(),
|
user_agent: http_util::get_user_agent(),
|
||||||
seed: program_state.flags.seed,
|
seed: program_state.flags.seed,
|
||||||
js_error_create_fn: Some(js_error_create_fn),
|
js_error_create_fn: Some(js_error_create_fn),
|
||||||
|
@ -295,6 +295,7 @@ async fn compile_command(
|
||||||
flags: Flags,
|
flags: Flags,
|
||||||
source_file: String,
|
source_file: String,
|
||||||
output: Option<PathBuf>,
|
output: Option<PathBuf>,
|
||||||
|
args: Vec<String>,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
if !flags.unstable {
|
if !flags.unstable {
|
||||||
exit_unstable("compile");
|
exit_unstable("compile");
|
||||||
|
@ -302,6 +303,8 @@ async fn compile_command(
|
||||||
|
|
||||||
let debug = flags.log_level == Some(log::Level::Debug);
|
let debug = flags.log_level == Some(log::Level::Debug);
|
||||||
|
|
||||||
|
let run_flags = standalone::compile_to_runtime_flags(flags.clone(), args)?;
|
||||||
|
|
||||||
let module_specifier = ModuleSpecifier::resolve_url_or_path(&source_file)?;
|
let module_specifier = ModuleSpecifier::resolve_url_or_path(&source_file)?;
|
||||||
let program_state = ProgramState::new(flags.clone())?;
|
let program_state = ProgramState::new(flags.clone())?;
|
||||||
|
|
||||||
|
@ -330,8 +333,7 @@ async fn compile_command(
|
||||||
colors::green("Compile"),
|
colors::green("Compile"),
|
||||||
module_specifier.to_string()
|
module_specifier.to_string()
|
||||||
);
|
);
|
||||||
create_standalone_binary(bundle_str.as_bytes().to_vec(), output.clone())
|
create_standalone_binary(bundle_str, run_flags, output.clone()).await?;
|
||||||
.await?;
|
|
||||||
|
|
||||||
info!("{} {}", colors::green("Emit"), output.display());
|
info!("{} {}", colors::green("Emit"), output.display());
|
||||||
|
|
||||||
|
@ -1069,6 +1071,7 @@ fn init_v8_flags(v8_flags: &[String]) {
|
||||||
let v8_flags_includes_help = v8_flags
|
let v8_flags_includes_help = v8_flags
|
||||||
.iter()
|
.iter()
|
||||||
.any(|flag| flag == "-help" || flag == "--help");
|
.any(|flag| flag == "-help" || flag == "--help");
|
||||||
|
// Keep in sync with `standalone.rs`.
|
||||||
let v8_flags = once("UNUSED_BUT_NECESSARY_ARG0".to_owned())
|
let v8_flags = once("UNUSED_BUT_NECESSARY_ARG0".to_owned())
|
||||||
.chain(v8_flags.iter().cloned())
|
.chain(v8_flags.iter().cloned())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
@ -1147,7 +1150,8 @@ fn get_subcommand(
|
||||||
DenoSubcommand::Compile {
|
DenoSubcommand::Compile {
|
||||||
source_file,
|
source_file,
|
||||||
output,
|
output,
|
||||||
} => compile_command(flags, source_file, output).boxed_local(),
|
args,
|
||||||
|
} => compile_command(flags, source_file, output, args).boxed_local(),
|
||||||
DenoSubcommand::Fmt {
|
DenoSubcommand::Fmt {
|
||||||
check,
|
check,
|
||||||
files,
|
files,
|
||||||
|
|
|
@ -20,12 +20,13 @@ use deno_runtime::permissions::Permissions;
|
||||||
use deno_core::error::anyhow;
|
use deno_core::error::anyhow;
|
||||||
use deno_core::error::get_custom_error_class;
|
use deno_core::error::get_custom_error_class;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
|
use deno_core::error::Context;
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
use deno_core::ModuleSource;
|
use deno_core::ModuleSource;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs::read_to_string;
|
use std::fs::read;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
@ -51,6 +52,7 @@ pub struct ProgramState {
|
||||||
pub lockfile: Option<Arc<Mutex<Lockfile>>>,
|
pub lockfile: Option<Arc<Mutex<Lockfile>>>,
|
||||||
pub maybe_import_map: Option<ImportMap>,
|
pub maybe_import_map: Option<ImportMap>,
|
||||||
pub maybe_inspector_server: Option<Arc<InspectorServer>>,
|
pub maybe_inspector_server: Option<Arc<InspectorServer>>,
|
||||||
|
pub ca_data: Option<Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProgramState {
|
impl ProgramState {
|
||||||
|
@ -59,12 +61,10 @@ impl ProgramState {
|
||||||
let dir = deno_dir::DenoDir::new(custom_root)?;
|
let dir = deno_dir::DenoDir::new(custom_root)?;
|
||||||
let deps_cache_location = dir.root.join("deps");
|
let deps_cache_location = dir.root.join("deps");
|
||||||
let http_cache = http_cache::HttpCache::new(&deps_cache_location);
|
let http_cache = http_cache::HttpCache::new(&deps_cache_location);
|
||||||
let ca_file_path =
|
let ca_file = flags.ca_file.clone().or_else(|| env::var("DENO_CERT").ok());
|
||||||
flags.ca_file.clone().or_else(|| env::var("DENO_CERT").ok());
|
let ca_data = match &ca_file {
|
||||||
|
Some(ca_file) => Some(read(ca_file).context("Failed to open ca file")?),
|
||||||
let ca_data: Option<String> = match ca_file_path.as_ref() {
|
|
||||||
None => None,
|
None => None,
|
||||||
Some(ca_file_path) => Some(read_to_string(ca_file_path)?),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let cache_usage = if flags.cached_only {
|
let cache_usage = if flags.cached_only {
|
||||||
|
@ -81,7 +81,7 @@ impl ProgramState {
|
||||||
http_cache,
|
http_cache,
|
||||||
cache_usage,
|
cache_usage,
|
||||||
!flags.no_remote,
|
!flags.no_remote,
|
||||||
ca_data.as_deref(),
|
ca_data.clone(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let lockfile = if let Some(filename) = &flags.lock {
|
let lockfile = if let Some(filename) = &flags.lock {
|
||||||
|
@ -125,6 +125,7 @@ impl ProgramState {
|
||||||
lockfile,
|
lockfile,
|
||||||
maybe_import_map,
|
maybe_import_map,
|
||||||
maybe_inspector_server,
|
maybe_inspector_server,
|
||||||
|
ca_data,
|
||||||
};
|
};
|
||||||
Ok(Arc::new(program_state))
|
Ok(Arc::new(program_state))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,17 @@
|
||||||
use crate::colors;
|
use crate::colors;
|
||||||
|
use crate::flags::DenoSubcommand;
|
||||||
use crate::flags::Flags;
|
use crate::flags::Flags;
|
||||||
use crate::tokio_util;
|
use crate::tokio_util;
|
||||||
use crate::version;
|
use crate::version;
|
||||||
use deno_core::error::bail;
|
use deno_core::error::bail;
|
||||||
use deno_core::error::type_error;
|
use deno_core::error::type_error;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
|
use deno_core::error::Context;
|
||||||
use deno_core::futures::FutureExt;
|
use deno_core::futures::FutureExt;
|
||||||
|
use deno_core::serde::Deserialize;
|
||||||
|
use deno_core::serde::Serialize;
|
||||||
|
use deno_core::serde_json;
|
||||||
|
use deno_core::v8_set_flags;
|
||||||
use deno_core::ModuleLoader;
|
use deno_core::ModuleLoader;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use deno_core::OpState;
|
use deno_core::OpState;
|
||||||
|
@ -15,43 +21,61 @@ use deno_runtime::worker::WorkerOptions;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::env::current_exe;
|
use std::env::current_exe;
|
||||||
|
use std::fs::read;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::io::Seek;
|
use std::io::Seek;
|
||||||
use std::io::SeekFrom;
|
use std::io::SeekFrom;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
use std::iter::once;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
struct Metadata {
|
||||||
|
flags: Flags,
|
||||||
|
ca_data: Option<Vec<u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
const MAGIC_TRAILER: &[u8; 8] = b"d3n0l4nd";
|
const MAGIC_TRAILER: &[u8; 8] = b"d3n0l4nd";
|
||||||
|
|
||||||
/// This function will try to run this binary as a standalone binary
|
/// This function will try to run this binary as a standalone binary
|
||||||
/// produced by `deno compile`. It determines if this is a stanalone
|
/// produced by `deno compile`. It determines if this is a stanalone
|
||||||
/// binary by checking for the magic trailer string `D3N0` at EOF-12.
|
/// binary by checking for the magic trailer string `D3N0` at EOF-12.
|
||||||
/// After the magic trailer is a u64 pointer to the start of the JS
|
/// The magic trailer is followed by:
|
||||||
/// file embedded in the binary. This file is read, and run. If no
|
/// - a u64 pointer to the JS bundle embedded in the binary
|
||||||
/// magic trailer is present, this function exits with Ok(()).
|
/// - a u64 pointer to JSON metadata (serialized flags) embedded in the binary
|
||||||
|
/// These are dereferenced, and the bundle is executed under the configuration
|
||||||
|
/// specified by the metadata. If no magic trailer is present, this function
|
||||||
|
/// exits with `Ok(())`.
|
||||||
pub fn try_run_standalone_binary(args: Vec<String>) -> Result<(), AnyError> {
|
pub fn try_run_standalone_binary(args: Vec<String>) -> Result<(), AnyError> {
|
||||||
let current_exe_path = current_exe()?;
|
let current_exe_path = current_exe()?;
|
||||||
|
|
||||||
let mut current_exe = File::open(current_exe_path)?;
|
let mut current_exe = File::open(current_exe_path)?;
|
||||||
let trailer_pos = current_exe.seek(SeekFrom::End(-16))?;
|
let trailer_pos = current_exe.seek(SeekFrom::End(-24))?;
|
||||||
let mut trailer = [0; 16];
|
let mut trailer = [0; 24];
|
||||||
current_exe.read_exact(&mut trailer)?;
|
current_exe.read_exact(&mut trailer)?;
|
||||||
let (magic_trailer, bundle_pos_arr) = trailer.split_at(8);
|
let (magic_trailer, rest) = trailer.split_at(8);
|
||||||
if magic_trailer == MAGIC_TRAILER {
|
if magic_trailer == MAGIC_TRAILER {
|
||||||
let bundle_pos_arr: &[u8; 8] = bundle_pos_arr.try_into()?;
|
let (bundle_pos, rest) = rest.split_at(8);
|
||||||
let bundle_pos = u64::from_be_bytes(*bundle_pos_arr);
|
let metadata_pos = rest;
|
||||||
|
let bundle_pos = u64_from_bytes(bundle_pos)?;
|
||||||
|
let metadata_pos = u64_from_bytes(metadata_pos)?;
|
||||||
|
let bundle_len = metadata_pos - bundle_pos;
|
||||||
|
let metadata_len = trailer_pos - metadata_pos;
|
||||||
current_exe.seek(SeekFrom::Start(bundle_pos))?;
|
current_exe.seek(SeekFrom::Start(bundle_pos))?;
|
||||||
|
|
||||||
let bundle_len = trailer_pos - bundle_pos;
|
let bundle = read_string_slice(&mut current_exe, bundle_pos, bundle_len)
|
||||||
let mut bundle = String::new();
|
.context("Failed to read source bundle from the current executable")?;
|
||||||
current_exe.take(bundle_len).read_to_string(&mut bundle)?;
|
let metadata =
|
||||||
// TODO: check amount of bytes read
|
read_string_slice(&mut current_exe, metadata_pos, metadata_len)
|
||||||
|
.context("Failed to read metadata from the current executable")?;
|
||||||
|
|
||||||
if let Err(err) = tokio_util::run_basic(run(bundle, args)) {
|
let mut metadata: Metadata = serde_json::from_str(&metadata).unwrap();
|
||||||
|
metadata.flags.argv.append(&mut args[1..].to_vec());
|
||||||
|
if let Err(err) = tokio_util::run_basic(run(bundle, metadata)) {
|
||||||
eprintln!("{}: {}", colors::red_bold("error"), err.to_string());
|
eprintln!("{}: {}", colors::red_bold("error"), err.to_string());
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
@ -61,6 +85,25 @@ pub fn try_run_standalone_binary(args: Vec<String>) -> Result<(), AnyError> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn u64_from_bytes(arr: &[u8]) -> Result<u64, AnyError> {
|
||||||
|
let fixed_arr: &[u8; 8] = arr
|
||||||
|
.try_into()
|
||||||
|
.context("Failed to convert the buffer into a fixed-size array")?;
|
||||||
|
Ok(u64::from_be_bytes(*fixed_arr))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_string_slice(
|
||||||
|
file: &mut File,
|
||||||
|
pos: u64,
|
||||||
|
len: u64,
|
||||||
|
) -> Result<String, AnyError> {
|
||||||
|
let mut string = String::new();
|
||||||
|
file.seek(SeekFrom::Start(pos))?;
|
||||||
|
file.take(len).read_to_string(&mut string)?;
|
||||||
|
// TODO: check amount of bytes read
|
||||||
|
Ok(string)
|
||||||
|
}
|
||||||
|
|
||||||
const SPECIFIER: &str = "file://$deno$/bundle.js";
|
const SPECIFIER: &str = "file://$deno$/bundle.js";
|
||||||
|
|
||||||
struct EmbeddedModuleLoader(String);
|
struct EmbeddedModuleLoader(String);
|
||||||
|
@ -106,28 +149,30 @@ impl ModuleLoader for EmbeddedModuleLoader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run(source_code: String, args: Vec<String>) -> Result<(), AnyError> {
|
async fn run(source_code: String, metadata: Metadata) -> Result<(), AnyError> {
|
||||||
let flags = Flags {
|
let Metadata { flags, ca_data } = metadata;
|
||||||
argv: args[1..].to_vec(),
|
|
||||||
// TODO(lucacasonato): remove once you can specify this correctly through embedded metadata
|
|
||||||
unstable: true,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
let main_module = ModuleSpecifier::resolve_url(SPECIFIER)?;
|
let main_module = ModuleSpecifier::resolve_url(SPECIFIER)?;
|
||||||
let permissions = Permissions::allow_all();
|
let permissions = Permissions::from_options(&flags.clone().into());
|
||||||
let module_loader = Rc::new(EmbeddedModuleLoader(source_code));
|
let module_loader = Rc::new(EmbeddedModuleLoader(source_code));
|
||||||
let create_web_worker_cb = Arc::new(|_| {
|
let create_web_worker_cb = Arc::new(|_| {
|
||||||
todo!("Worker are currently not supported in standalone binaries");
|
todo!("Worker are currently not supported in standalone binaries");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Keep in sync with `main.rs`.
|
||||||
|
v8_set_flags(
|
||||||
|
once("UNUSED_BUT_NECESSARY_ARG0".to_owned())
|
||||||
|
.chain(flags.v8_flags.iter().cloned())
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
);
|
||||||
|
// TODO(nayeemrmn): Unify this Flags -> WorkerOptions mapping with `deno run`.
|
||||||
let options = WorkerOptions {
|
let options = WorkerOptions {
|
||||||
apply_source_maps: false,
|
apply_source_maps: false,
|
||||||
args: flags.argv.clone(),
|
args: flags.argv.clone(),
|
||||||
debug_flag: false,
|
debug_flag: flags.log_level.map_or(false, |l| l == log::Level::Debug),
|
||||||
user_agent: crate::http_util::get_user_agent(),
|
user_agent: crate::http_util::get_user_agent(),
|
||||||
unstable: true,
|
unstable: flags.unstable,
|
||||||
ca_filepath: None,
|
ca_data,
|
||||||
seed: None,
|
seed: flags.seed,
|
||||||
js_error_create_fn: None,
|
js_error_create_fn: None,
|
||||||
create_web_worker_cb,
|
create_web_worker_cb,
|
||||||
attach_inspector: false,
|
attach_inspector: false,
|
||||||
|
@ -152,19 +197,31 @@ async fn run(source_code: String, args: Vec<String>) -> Result<(), AnyError> {
|
||||||
/// This functions creates a standalone deno binary by appending a bundle
|
/// This functions creates a standalone deno binary by appending a bundle
|
||||||
/// and magic trailer to the currently executing binary.
|
/// and magic trailer to the currently executing binary.
|
||||||
pub async fn create_standalone_binary(
|
pub async fn create_standalone_binary(
|
||||||
mut source_code: Vec<u8>,
|
source_code: String,
|
||||||
|
flags: Flags,
|
||||||
output: PathBuf,
|
output: PathBuf,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
|
let mut source_code = source_code.as_bytes().to_vec();
|
||||||
|
let ca_data = match &flags.ca_file {
|
||||||
|
Some(ca_file) => Some(read(ca_file)?),
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
let metadata = Metadata { flags, ca_data };
|
||||||
|
let mut metadata = serde_json::to_string(&metadata)?.as_bytes().to_vec();
|
||||||
let original_binary_path = std::env::current_exe()?;
|
let original_binary_path = std::env::current_exe()?;
|
||||||
let mut original_bin = tokio::fs::read(original_binary_path).await?;
|
let mut original_bin = tokio::fs::read(original_binary_path).await?;
|
||||||
|
|
||||||
|
let bundle_pos = original_bin.len();
|
||||||
|
let metadata_pos = bundle_pos + source_code.len();
|
||||||
let mut trailer = MAGIC_TRAILER.to_vec();
|
let mut trailer = MAGIC_TRAILER.to_vec();
|
||||||
trailer.write_all(&original_bin.len().to_be_bytes())?;
|
trailer.write_all(&bundle_pos.to_be_bytes())?;
|
||||||
|
trailer.write_all(&metadata_pos.to_be_bytes())?;
|
||||||
|
|
||||||
let mut final_bin =
|
let mut final_bin =
|
||||||
Vec::with_capacity(original_bin.len() + source_code.len() + trailer.len());
|
Vec::with_capacity(original_bin.len() + source_code.len() + trailer.len());
|
||||||
final_bin.append(&mut original_bin);
|
final_bin.append(&mut original_bin);
|
||||||
final_bin.append(&mut source_code);
|
final_bin.append(&mut source_code);
|
||||||
|
final_bin.append(&mut metadata);
|
||||||
final_bin.append(&mut trailer);
|
final_bin.append(&mut trailer);
|
||||||
|
|
||||||
let output =
|
let output =
|
||||||
|
@ -181,13 +238,18 @@ pub async fn create_standalone_binary(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we don't overwrite any file not created by Deno compiler.
|
// Make sure we don't overwrite any file not created by Deno compiler.
|
||||||
// Check for magic trailer in last 16 bytes
|
// Check for magic trailer in last 24 bytes.
|
||||||
|
let mut has_trailer = false;
|
||||||
let mut output_file = File::open(&output)?;
|
let mut output_file = File::open(&output)?;
|
||||||
output_file.seek(SeekFrom::End(-16))?;
|
// This seek may fail because the file is too small to possibly be
|
||||||
let mut trailer = [0; 16];
|
// `deno compile` output.
|
||||||
output_file.read_exact(&mut trailer)?;
|
if output_file.seek(SeekFrom::End(-24)).is_ok() {
|
||||||
let (magic_trailer, _) = trailer.split_at(8);
|
let mut trailer = [0; 24];
|
||||||
if magic_trailer != MAGIC_TRAILER {
|
output_file.read_exact(&mut trailer)?;
|
||||||
|
let (magic_trailer, _) = trailer.split_at(8);
|
||||||
|
has_trailer = magic_trailer == MAGIC_TRAILER;
|
||||||
|
}
|
||||||
|
if !has_trailer {
|
||||||
bail!("Could not compile: cannot overwrite {:?}.", &output);
|
bail!("Could not compile: cannot overwrite {:?}.", &output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -201,3 +263,52 @@ pub async fn create_standalone_binary(
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Transform the flags passed to `deno compile` to flags that would be used at
|
||||||
|
/// runtime, as if `deno run` were used.
|
||||||
|
/// - Flags that affect module resolution, loading, type checking, etc. aren't
|
||||||
|
/// applicable at runtime so are set to their defaults like `false`.
|
||||||
|
/// - Other flags are inherited.
|
||||||
|
pub fn compile_to_runtime_flags(
|
||||||
|
flags: Flags,
|
||||||
|
baked_args: Vec<String>,
|
||||||
|
) -> Result<Flags, AnyError> {
|
||||||
|
// IMPORTANT: Don't abbreviate any of this to `..flags` or
|
||||||
|
// `..Default::default()`. That forces us to explicitly consider how any
|
||||||
|
// change to `Flags` should be reflected here.
|
||||||
|
Ok(Flags {
|
||||||
|
argv: baked_args,
|
||||||
|
subcommand: DenoSubcommand::Run {
|
||||||
|
script: "placeholder".to_string(),
|
||||||
|
},
|
||||||
|
allow_env: flags.allow_env,
|
||||||
|
allow_hrtime: flags.allow_hrtime,
|
||||||
|
allow_net: flags.allow_net,
|
||||||
|
allow_plugin: flags.allow_plugin,
|
||||||
|
allow_read: flags.allow_read,
|
||||||
|
allow_run: flags.allow_run,
|
||||||
|
allow_write: flags.allow_write,
|
||||||
|
cache_blocklist: vec![],
|
||||||
|
ca_file: flags.ca_file,
|
||||||
|
cached_only: false,
|
||||||
|
config_path: None,
|
||||||
|
coverage_dir: flags.coverage_dir,
|
||||||
|
ignore: vec![],
|
||||||
|
import_map_path: None,
|
||||||
|
inspect: None,
|
||||||
|
inspect_brk: None,
|
||||||
|
lock: None,
|
||||||
|
lock_write: false,
|
||||||
|
log_level: flags.log_level,
|
||||||
|
no_check: false,
|
||||||
|
no_prompts: flags.no_prompts,
|
||||||
|
no_remote: false,
|
||||||
|
reload: false,
|
||||||
|
repl: false,
|
||||||
|
seed: flags.seed,
|
||||||
|
unstable: flags.unstable,
|
||||||
|
v8_flags: flags.v8_flags,
|
||||||
|
version: false,
|
||||||
|
watch: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -4686,6 +4686,8 @@ fn standalone_args() {
|
||||||
.arg("--output")
|
.arg("--output")
|
||||||
.arg(&exe)
|
.arg(&exe)
|
||||||
.arg("./cli/tests/028_args.ts")
|
.arg("./cli/tests/028_args.ts")
|
||||||
|
.arg("a")
|
||||||
|
.arg("b")
|
||||||
.stdout(std::process::Stdio::piped())
|
.stdout(std::process::Stdio::piped())
|
||||||
.spawn()
|
.spawn()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -4702,7 +4704,7 @@ fn standalone_args() {
|
||||||
.wait_with_output()
|
.wait_with_output()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(output.status.success());
|
assert!(output.status.success());
|
||||||
assert_eq!(output.stdout, b"foo\n--bar\n--unstable\n");
|
assert_eq!(output.stdout, b"a\nb\nfoo\n--bar\n--unstable\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -4789,9 +4791,9 @@ fn compile_with_directory_exists_error() {
|
||||||
.current_dir(util::root_path())
|
.current_dir(util::root_path())
|
||||||
.arg("compile")
|
.arg("compile")
|
||||||
.arg("--unstable")
|
.arg("--unstable")
|
||||||
.arg("./cli/tests/028_args.ts")
|
|
||||||
.arg("--output")
|
.arg("--output")
|
||||||
.arg(&exe)
|
.arg(&exe)
|
||||||
|
.arg("./cli/tests/028_args.ts")
|
||||||
.stderr(std::process::Stdio::piped())
|
.stderr(std::process::Stdio::piped())
|
||||||
.spawn()
|
.spawn()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -4818,9 +4820,9 @@ fn compile_with_conflict_file_exists_error() {
|
||||||
.current_dir(util::root_path())
|
.current_dir(util::root_path())
|
||||||
.arg("compile")
|
.arg("compile")
|
||||||
.arg("--unstable")
|
.arg("--unstable")
|
||||||
.arg("./cli/tests/028_args.ts")
|
|
||||||
.arg("--output")
|
.arg("--output")
|
||||||
.arg(&exe)
|
.arg(&exe)
|
||||||
|
.arg("./cli/tests/028_args.ts")
|
||||||
.stderr(std::process::Stdio::piped())
|
.stderr(std::process::Stdio::piped())
|
||||||
.spawn()
|
.spawn()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -4830,6 +4832,7 @@ fn compile_with_conflict_file_exists_error() {
|
||||||
let expected_stderr =
|
let expected_stderr =
|
||||||
format!("Could not compile: cannot overwrite {:?}.\n", &exe);
|
format!("Could not compile: cannot overwrite {:?}.\n", &exe);
|
||||||
let stderr = String::from_utf8(output.stderr).unwrap();
|
let stderr = String::from_utf8(output.stderr).unwrap();
|
||||||
|
dbg!(&stderr);
|
||||||
assert!(stderr.contains(&expected_stderr));
|
assert!(stderr.contains(&expected_stderr));
|
||||||
assert!(std::fs::read(&exe)
|
assert!(std::fs::read(&exe)
|
||||||
.expect("cannot read file")
|
.expect("cannot read file")
|
||||||
|
@ -4848,9 +4851,9 @@ fn compile_and_overwrite_file() {
|
||||||
.current_dir(util::root_path())
|
.current_dir(util::root_path())
|
||||||
.arg("compile")
|
.arg("compile")
|
||||||
.arg("--unstable")
|
.arg("--unstable")
|
||||||
.arg("./cli/tests/028_args.ts")
|
|
||||||
.arg("--output")
|
.arg("--output")
|
||||||
.arg(&exe)
|
.arg(&exe)
|
||||||
|
.arg("./cli/tests/028_args.ts")
|
||||||
.stderr(std::process::Stdio::piped())
|
.stderr(std::process::Stdio::piped())
|
||||||
.spawn()
|
.spawn()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -4863,9 +4866,9 @@ fn compile_and_overwrite_file() {
|
||||||
.current_dir(util::root_path())
|
.current_dir(util::root_path())
|
||||||
.arg("compile")
|
.arg("compile")
|
||||||
.arg("--unstable")
|
.arg("--unstable")
|
||||||
.arg("./cli/tests/028_args.ts")
|
|
||||||
.arg("--output")
|
.arg("--output")
|
||||||
.arg(&exe)
|
.arg(&exe)
|
||||||
|
.arg("./cli/tests/028_args.ts")
|
||||||
.stderr(std::process::Stdio::piped())
|
.stderr(std::process::Stdio::piped())
|
||||||
.spawn()
|
.spawn()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -4873,3 +4876,42 @@ fn compile_and_overwrite_file() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(recompile_output.status.success());
|
assert!(recompile_output.status.success());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn standalone_runtime_flags() {
|
||||||
|
let dir = TempDir::new().expect("tempdir fail");
|
||||||
|
let exe = if cfg!(windows) {
|
||||||
|
dir.path().join("flags.exe")
|
||||||
|
} else {
|
||||||
|
dir.path().join("flags")
|
||||||
|
};
|
||||||
|
let output = util::deno_cmd()
|
||||||
|
.current_dir(util::root_path())
|
||||||
|
.arg("compile")
|
||||||
|
.arg("--unstable")
|
||||||
|
.arg("--allow-read")
|
||||||
|
.arg("--seed")
|
||||||
|
.arg("1")
|
||||||
|
.arg("--output")
|
||||||
|
.arg(&exe)
|
||||||
|
.arg("./cli/tests/standalone_runtime_flags.ts")
|
||||||
|
.stdout(std::process::Stdio::piped())
|
||||||
|
.spawn()
|
||||||
|
.unwrap()
|
||||||
|
.wait_with_output()
|
||||||
|
.unwrap();
|
||||||
|
assert!(output.status.success());
|
||||||
|
let output = Command::new(exe)
|
||||||
|
.stdout(std::process::Stdio::piped())
|
||||||
|
.stderr(std::process::Stdio::piped())
|
||||||
|
.spawn()
|
||||||
|
.unwrap()
|
||||||
|
.wait_with_output()
|
||||||
|
.unwrap();
|
||||||
|
assert!(!output.status.success());
|
||||||
|
let stdout_str = String::from_utf8(output.stdout).unwrap();
|
||||||
|
assert_eq!(util::strip_ansi_codes(&stdout_str), "0.147205063401058\n");
|
||||||
|
let stderr_str = String::from_utf8(output.stderr).unwrap();
|
||||||
|
assert!(util::strip_ansi_codes(&stderr_str)
|
||||||
|
.contains("PermissionDenied: write access"));
|
||||||
|
}
|
||||||
|
|
3
cli/tests/standalone_runtime_flags.ts
Normal file
3
cli/tests/standalone_runtime_flags.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
console.log(Math.random());
|
||||||
|
await Deno.stat(".");
|
||||||
|
await Deno.create("foo.txt");
|
|
@ -5,6 +5,7 @@ and TypeScript:
|
||||||
|
|
||||||
- [bundler (`deno bundle`)](./tools/bundler.md)
|
- [bundler (`deno bundle`)](./tools/bundler.md)
|
||||||
- [compiling executables (`deno compile`)](./tools/compiler.md)
|
- [compiling executables (`deno compile`)](./tools/compiler.md)
|
||||||
|
- [installer (`deno install`)](./tools/script_installer.md)
|
||||||
- [dependency inspector (`deno info`)](./tools/dependency_inspector.md)
|
- [dependency inspector (`deno info`)](./tools/dependency_inspector.md)
|
||||||
- [documentation generator (`deno doc`)](./tools/documentation_generator.md)
|
- [documentation generator (`deno doc`)](./tools/documentation_generator.md)
|
||||||
- [formatter (`deno fmt`)](./tools/formatter.md)
|
- [formatter (`deno fmt`)](./tools/formatter.md)
|
||||||
|
|
|
@ -3,16 +3,34 @@
|
||||||
> Since the compile functionality is relatively new, the `--unstable` flag has
|
> Since the compile functionality is relatively new, the `--unstable` flag has
|
||||||
> to be set in order for the command to work.
|
> to be set in order for the command to work.
|
||||||
|
|
||||||
`deno compile [SRC] [OUT]` will compile the script into a self contained
|
`deno compile [--output <OUT>] <SRC>` will compile the script into a
|
||||||
executable.
|
self-contained executable.
|
||||||
|
|
||||||
```
|
```
|
||||||
> deno compile --unstable https://deno.land/std/http/file_server.ts
|
> deno compile --unstable https://deno.land/std/examples/welcome.ts
|
||||||
```
|
```
|
||||||
|
|
||||||
If you omit the `OUT` parameter, the name of the executable file will be
|
If you omit the `OUT` parameter, the name of the executable file will be
|
||||||
inferred.
|
inferred.
|
||||||
|
|
||||||
|
### Flags
|
||||||
|
|
||||||
|
As with [`deno install`](./script_installer.md), the runtime flags used to
|
||||||
|
execute the script must be specified at compilation time. This includes
|
||||||
|
permission flags.
|
||||||
|
|
||||||
|
```
|
||||||
|
> deno compile --unstable --allow-read --allow-net https://deno.land/std/http/file_server.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
[Script arguments](../getting_started/command_line_interface.md#script-arguments)
|
||||||
|
can be partially embedded.
|
||||||
|
|
||||||
|
```
|
||||||
|
> deno compile --unstable --allow-read --allow-net https://deno.land/std/http/file_server.ts -p 8080
|
||||||
|
> ./file_server --help
|
||||||
|
```
|
||||||
|
|
||||||
### Cross Compilation
|
### Cross Compilation
|
||||||
|
|
||||||
Cross compiling binaries for different platforms is not currently possible.
|
Cross compiling binaries for different platforms is not currently possible.
|
||||||
|
|
|
@ -26,7 +26,7 @@ async fn main() -> Result<(), AnyError> {
|
||||||
args: vec![],
|
args: vec![],
|
||||||
debug_flag: false,
|
debug_flag: false,
|
||||||
unstable: false,
|
unstable: false,
|
||||||
ca_filepath: None,
|
ca_data: None,
|
||||||
user_agent: "hello_runtime".to_string(),
|
user_agent: "hello_runtime".to_string(),
|
||||||
seed: None,
|
seed: None,
|
||||||
js_error_create_fn: None,
|
js_error_create_fn: None,
|
||||||
|
|
|
@ -7,14 +7,12 @@ use deno_fetch::reqwest::header::HeaderMap;
|
||||||
use deno_fetch::reqwest::header::USER_AGENT;
|
use deno_fetch::reqwest::header::USER_AGENT;
|
||||||
use deno_fetch::reqwest::redirect::Policy;
|
use deno_fetch::reqwest::redirect::Policy;
|
||||||
use deno_fetch::reqwest::Client;
|
use deno_fetch::reqwest::Client;
|
||||||
use std::fs::File;
|
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
/// Create new instance of async reqwest::Client. This client supports
|
/// Create new instance of async reqwest::Client. This client supports
|
||||||
/// proxies and doesn't follow redirects.
|
/// proxies and doesn't follow redirects.
|
||||||
pub fn create_http_client(
|
pub fn create_http_client(
|
||||||
user_agent: String,
|
user_agent: String,
|
||||||
ca_file: Option<&str>,
|
ca_data: Option<Vec<u8>>,
|
||||||
) -> Result<Client, AnyError> {
|
) -> Result<Client, AnyError> {
|
||||||
let mut headers = HeaderMap::new();
|
let mut headers = HeaderMap::new();
|
||||||
headers.insert(USER_AGENT, user_agent.parse().unwrap());
|
headers.insert(USER_AGENT, user_agent.parse().unwrap());
|
||||||
|
@ -23,10 +21,8 @@ pub fn create_http_client(
|
||||||
.default_headers(headers)
|
.default_headers(headers)
|
||||||
.use_rustls_tls();
|
.use_rustls_tls();
|
||||||
|
|
||||||
if let Some(ca_file) = ca_file {
|
if let Some(ca_data) = ca_data {
|
||||||
let mut buf = Vec::new();
|
let cert = reqwest::Certificate::from_pem(&ca_data)?;
|
||||||
File::open(ca_file)?.read_to_end(&mut buf)?;
|
|
||||||
let cert = reqwest::Certificate::from_pem(&buf)?;
|
|
||||||
builder = builder.add_root_certificate(cert);
|
builder = builder.add_root_certificate(cert);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,13 +6,13 @@ use deno_fetch::reqwest;
|
||||||
pub fn init(
|
pub fn init(
|
||||||
rt: &mut deno_core::JsRuntime,
|
rt: &mut deno_core::JsRuntime,
|
||||||
user_agent: String,
|
user_agent: String,
|
||||||
maybe_ca_file: Option<&str>,
|
ca_data: Option<Vec<u8>>,
|
||||||
) {
|
) {
|
||||||
{
|
{
|
||||||
let op_state = rt.op_state();
|
let op_state = rt.op_state();
|
||||||
let mut state = op_state.borrow_mut();
|
let mut state = op_state.borrow_mut();
|
||||||
state.put::<reqwest::Client>({
|
state.put::<reqwest::Client>({
|
||||||
http_util::create_http_client(user_agent, maybe_ca_file).unwrap()
|
http_util::create_http_client(user_agent, ca_data).unwrap()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
super::reg_json_async(rt, "op_fetch", deno_fetch::op_fetch::<Permissions>);
|
super::reg_json_async(rt, "op_fetch", deno_fetch::op_fetch::<Permissions>);
|
||||||
|
|
|
@ -23,8 +23,8 @@ use http::{Method, Request, Uri};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::fs::File;
|
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
|
use std::io::Cursor;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
|
@ -39,20 +39,20 @@ use tokio_tungstenite::{client_async, WebSocketStream};
|
||||||
use webpki::DNSNameRef;
|
use webpki::DNSNameRef;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct WsCaFile(String);
|
struct WsCaData(Vec<u8>);
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct WsUserAgent(String);
|
struct WsUserAgent(String);
|
||||||
|
|
||||||
pub fn init(
|
pub fn init(
|
||||||
rt: &mut deno_core::JsRuntime,
|
rt: &mut deno_core::JsRuntime,
|
||||||
maybe_ca_file: Option<&str>,
|
ca_data: Option<Vec<u8>>,
|
||||||
user_agent: String,
|
user_agent: String,
|
||||||
) {
|
) {
|
||||||
{
|
{
|
||||||
let op_state = rt.op_state();
|
let op_state = rt.op_state();
|
||||||
let mut state = op_state.borrow_mut();
|
let mut state = op_state.borrow_mut();
|
||||||
if let Some(ca_file) = maybe_ca_file {
|
if let Some(ca_data) = ca_data {
|
||||||
state.put::<WsCaFile>(WsCaFile(ca_file.to_string()));
|
state.put::<WsCaData>(WsCaData(ca_data));
|
||||||
}
|
}
|
||||||
state.put::<WsUserAgent>(WsUserAgent(user_agent));
|
state.put::<WsUserAgent>(WsUserAgent(user_agent));
|
||||||
}
|
}
|
||||||
|
@ -130,7 +130,7 @@ pub async fn op_ws_create(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let maybe_ca_file = state.borrow().try_borrow::<WsCaFile>().cloned();
|
let ws_ca_data = state.borrow().try_borrow::<WsCaData>().cloned();
|
||||||
let user_agent = state.borrow().borrow::<WsUserAgent>().0.clone();
|
let user_agent = state.borrow().borrow::<WsUserAgent>().0.clone();
|
||||||
let uri: Uri = args.url.parse()?;
|
let uri: Uri = args.url.parse()?;
|
||||||
let mut request = Request::builder().method(Method::GET).uri(&uri);
|
let mut request = Request::builder().method(Method::GET).uri(&uri);
|
||||||
|
@ -163,9 +163,8 @@ pub async fn op_ws_create(
|
||||||
.root_store
|
.root_store
|
||||||
.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
|
.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
|
||||||
|
|
||||||
if let Some(ws_ca_file) = maybe_ca_file {
|
if let Some(ws_ca_data) = ws_ca_data {
|
||||||
let key_file = File::open(ws_ca_file.0)?;
|
let reader = &mut BufReader::new(Cursor::new(ws_ca_data.0));
|
||||||
let reader = &mut BufReader::new(key_file);
|
|
||||||
config.root_store.add_pem_file(reader).unwrap();
|
config.root_store.add_pem_file(reader).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -137,7 +137,7 @@ pub struct WebWorkerOptions {
|
||||||
pub args: Vec<String>,
|
pub args: Vec<String>,
|
||||||
pub debug_flag: bool,
|
pub debug_flag: bool,
|
||||||
pub unstable: bool,
|
pub unstable: bool,
|
||||||
pub ca_filepath: Option<String>,
|
pub ca_data: Option<Vec<u8>>,
|
||||||
pub user_agent: String,
|
pub user_agent: String,
|
||||||
pub seed: Option<u64>,
|
pub seed: Option<u64>,
|
||||||
pub module_loader: Rc<dyn ModuleLoader>,
|
pub module_loader: Rc<dyn ModuleLoader>,
|
||||||
|
@ -219,7 +219,7 @@ impl WebWorker {
|
||||||
ops::fetch::init(
|
ops::fetch::init(
|
||||||
js_runtime,
|
js_runtime,
|
||||||
options.user_agent.clone(),
|
options.user_agent.clone(),
|
||||||
options.ca_filepath.as_deref(),
|
options.ca_data.clone(),
|
||||||
);
|
);
|
||||||
ops::timers::init(js_runtime);
|
ops::timers::init(js_runtime);
|
||||||
ops::worker_host::init(
|
ops::worker_host::init(
|
||||||
|
@ -237,7 +237,7 @@ impl WebWorker {
|
||||||
ops::io::init(js_runtime);
|
ops::io::init(js_runtime);
|
||||||
ops::websocket::init(
|
ops::websocket::init(
|
||||||
js_runtime,
|
js_runtime,
|
||||||
options.ca_filepath.as_deref(),
|
options.ca_data.clone(),
|
||||||
options.user_agent.clone(),
|
options.user_agent.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -483,7 +483,7 @@ mod tests {
|
||||||
apply_source_maps: false,
|
apply_source_maps: false,
|
||||||
debug_flag: false,
|
debug_flag: false,
|
||||||
unstable: false,
|
unstable: false,
|
||||||
ca_filepath: None,
|
ca_data: None,
|
||||||
user_agent: "x".to_string(),
|
user_agent: "x".to_string(),
|
||||||
seed: None,
|
seed: None,
|
||||||
module_loader,
|
module_loader,
|
||||||
|
|
|
@ -45,7 +45,7 @@ pub struct WorkerOptions {
|
||||||
pub args: Vec<String>,
|
pub args: Vec<String>,
|
||||||
pub debug_flag: bool,
|
pub debug_flag: bool,
|
||||||
pub unstable: bool,
|
pub unstable: bool,
|
||||||
pub ca_filepath: Option<String>,
|
pub ca_data: Option<Vec<u8>>,
|
||||||
pub user_agent: String,
|
pub user_agent: String,
|
||||||
pub seed: Option<u64>,
|
pub seed: Option<u64>,
|
||||||
pub module_loader: Rc<dyn ModuleLoader>,
|
pub module_loader: Rc<dyn ModuleLoader>,
|
||||||
|
@ -114,7 +114,7 @@ impl MainWorker {
|
||||||
ops::fetch::init(
|
ops::fetch::init(
|
||||||
js_runtime,
|
js_runtime,
|
||||||
options.user_agent.clone(),
|
options.user_agent.clone(),
|
||||||
options.ca_filepath.as_deref(),
|
options.ca_data.clone(),
|
||||||
);
|
);
|
||||||
ops::timers::init(js_runtime);
|
ops::timers::init(js_runtime);
|
||||||
ops::worker_host::init(
|
ops::worker_host::init(
|
||||||
|
@ -143,7 +143,7 @@ impl MainWorker {
|
||||||
ops::tty::init(js_runtime);
|
ops::tty::init(js_runtime);
|
||||||
ops::websocket::init(
|
ops::websocket::init(
|
||||||
js_runtime,
|
js_runtime,
|
||||||
options.ca_filepath.as_deref(),
|
options.ca_data.clone(),
|
||||||
options.user_agent.clone(),
|
options.user_agent.clone(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -270,7 +270,7 @@ mod tests {
|
||||||
args: vec![],
|
args: vec![],
|
||||||
debug_flag: false,
|
debug_flag: false,
|
||||||
unstable: false,
|
unstable: false,
|
||||||
ca_filepath: None,
|
ca_data: None,
|
||||||
seed: None,
|
seed: None,
|
||||||
js_error_create_fn: None,
|
js_error_create_fn: None,
|
||||||
create_web_worker_cb: Arc::new(|_| unreachable!()),
|
create_web_worker_cb: Arc::new(|_| unreachable!()),
|
||||||
|
|
Loading…
Add table
Reference in a new issue