diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 7c433e51430b11..e27dc37b377337 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -14,6 +14,10 @@ default-run = "deno" name = "deno" path = "main.rs" +[[bin]] +name = "denort" +path = "denort.rs" + [[bench]] name = "deno_bench" harness = false diff --git a/cli/bench/main.rs b/cli/bench/main.rs index ea693fb3ad0f44..d796237d1f6c4f 100644 --- a/cli/bench/main.rs +++ b/cli/bench/main.rs @@ -202,6 +202,12 @@ fn get_binary_sizes(target_dir: &PathBuf) -> Result { Value::Number(Number::from(test_util::deno_exe_path().metadata()?.len())), ); + // add up size for denort + sizes.insert( + "denort".to_string(), + Value::Number(Number::from(test_util::denort_exe_path().metadata()?.len())), + ); + // add up size for everything in target/release/deps/libswc* let swc_size = rlib_size(&target_dir, "libswc"); println!("swc {} bytes", swc_size); diff --git a/cli/denort.rs b/cli/denort.rs new file mode 100644 index 00000000000000..e59071743f5885 --- /dev/null +++ b/cli/denort.rs @@ -0,0 +1,26 @@ +// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. + +mod flags_rt; +mod rt; +mod version; + +fn main() { + #[cfg(windows)] + deno_runtime::colors::enable_ansi(); // For Windows 10 + + let args: Vec = std::env::args().collect(); + if let Err(err) = rt::try_run_standalone_binary(args) { + eprintln!( + "{}: {}", + deno_runtime::colors::red_bold("error"), + err.to_string() + ); + std::process::exit(1); + } + + eprintln!( + "{}: This executable is used internally by 'deno compile', it is not meant to be invoked directly.", + deno_runtime::colors::red_bold("error") + ); + std::process::exit(1); +} diff --git a/cli/flags.rs b/cli/flags.rs index da0f8ad0e49c08..1457e89dfed110 100644 --- a/cli/flags.rs +++ b/cli/flags.rs @@ -6,197 +6,14 @@ use clap::Arg; use clap::ArgMatches; use clap::ArgSettings; 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 log::Level; -use std::fmt; use std::net::SocketAddr; use std::path::PathBuf; use std::str::FromStr; use tempfile::TempDir; -#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] -pub enum DenoSubcommand { - Bundle { - source_file: String, - out_file: Option, - }, - Cache { - files: Vec, - }, - Compile { - source_file: String, - output: Option, - args: Vec, - }, - Completions { - buf: Box<[u8]>, - }, - Doc { - private: bool, - json: bool, - source_file: Option, - filter: Option, - }, - Eval { - print: bool, - code: String, - as_typescript: bool, - }, - Fmt { - check: bool, - files: Vec, - ignore: Vec, - }, - Info { - json: bool, - file: Option, - }, - Install { - module_url: String, - args: Vec, - name: Option, - root: Option, - force: bool, - }, - LanguageServer, - Lint { - files: Vec, - ignore: Vec, - rules: bool, - json: bool, - }, - Repl, - Run { - script: String, - }, - Test { - no_run: bool, - fail_fast: bool, - quiet: bool, - allow_none: bool, - include: Option>, - filter: Option, - }, - Types, - Upgrade { - dry_run: bool, - force: bool, - canary: bool, - version: Option, - output: Option, - ca_file: Option, - }, -} - -impl Default for DenoSubcommand { - fn default() -> DenoSubcommand { - DenoSubcommand::Repl - } -} - -fn deserialize_maybe_log_level<'de, D>(d: D) -> Result, D::Error> -where - D: Deserializer<'de>, -{ - struct OptionalLogLevelVisitor; - impl<'de> de::Visitor<'de> for OptionalLogLevelVisitor { - type Value = Option; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "null or a valid log level string") - } - - fn visit_none(self) -> Result - where - E: de::Error, - { - Ok(None) - } - - fn visit_some(self, d: D) -> Result - 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(self, s: &str) -> Result - 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( - maybe_level: &Option, - s: S, -) -> Result -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 { - /// Vector of CLI arguments - these are user script arguments, all Deno - /// specific flags are removed. - pub argv: Vec, - pub subcommand: DenoSubcommand, - - pub allow_env: bool, - pub allow_hrtime: bool, - pub allow_net: Option>, - pub allow_plugin: bool, - pub allow_read: Option>, - pub allow_run: bool, - pub allow_write: Option>, - pub cache_blocklist: Vec, - pub ca_file: Option, - pub cached_only: bool, - pub config_path: Option, - pub coverage_dir: Option, - pub ignore: Vec, - pub import_map_path: Option, - pub inspect: Option, - pub inspect_brk: Option, - pub lock: Option, - pub lock_write: bool, - #[serde(deserialize_with = "deserialize_maybe_log_level")] - #[serde(serialize_with = "serialize_maybe_log_level")] - pub log_level: Option, - pub no_check: bool, - pub no_prompts: bool, - pub no_remote: bool, - pub reload: bool, - pub repl: bool, - pub seed: Option, - pub unstable: bool, - pub v8_flags: Vec, - pub version: bool, - pub watch: bool, -} +pub use crate::flags_rt::DenoSubcommand; +pub use crate::flags_rt::Flags; fn join_paths(allowlist: &[PathBuf], d: &str) -> String { allowlist @@ -265,20 +82,6 @@ impl Flags { } } -impl From for PermissionsOptions { - fn from(flags: Flags) -> Self { - Self { - 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, - } - } -} - static ENV_VARIABLES_HELP: &str = "ENVIRONMENT VARIABLES: DENO_DIR Set the cache directory DENO_INSTALL_ROOT Set deno install's output directory diff --git a/cli/flags_rt.rs b/cli/flags_rt.rs new file mode 100644 index 00000000000000..f55ca6d1da00ee --- /dev/null +++ b/cli/flags_rt.rs @@ -0,0 +1,206 @@ +// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. + +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 log::Level; +use std::fmt; +use std::net::SocketAddr; +use std::path::PathBuf; +use std::str::FromStr; + +#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize)] +pub struct Flags { + /// Vector of CLI arguments - these are user script arguments, all Deno + /// specific flags are removed. + pub argv: Vec, + pub subcommand: DenoSubcommand, + + pub allow_env: bool, + pub allow_hrtime: bool, + pub allow_net: Option>, + pub allow_plugin: bool, + pub allow_read: Option>, + pub allow_run: bool, + pub allow_write: Option>, + pub cache_blocklist: Vec, + pub ca_file: Option, + pub cached_only: bool, + pub config_path: Option, + pub coverage_dir: Option, + pub ignore: Vec, + pub import_map_path: Option, + pub inspect: Option, + pub inspect_brk: Option, + pub lock: Option, + pub lock_write: bool, + #[serde(deserialize_with = "deserialize_maybe_log_level")] + #[serde(serialize_with = "serialize_maybe_log_level")] + pub log_level: Option, + pub no_check: bool, + pub no_prompts: bool, + pub no_remote: bool, + pub reload: bool, + pub repl: bool, + pub seed: Option, + pub unstable: bool, + pub v8_flags: Vec, + pub version: bool, + pub watch: bool, +} + +impl From for PermissionsOptions { + fn from(flags: Flags) -> Self { + Self { + 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, + } + } +} + +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] +pub enum DenoSubcommand { + Bundle { + source_file: String, + out_file: Option, + }, + Cache { + files: Vec, + }, + Compile { + source_file: String, + output: Option, + args: Vec, + }, + Completions { + buf: Box<[u8]>, + }, + Doc { + private: bool, + json: bool, + source_file: Option, + filter: Option, + }, + Eval { + print: bool, + code: String, + as_typescript: bool, + }, + Fmt { + check: bool, + files: Vec, + ignore: Vec, + }, + Info { + json: bool, + file: Option, + }, + Install { + module_url: String, + args: Vec, + name: Option, + root: Option, + force: bool, + }, + LanguageServer, + Lint { + files: Vec, + ignore: Vec, + rules: bool, + json: bool, + }, + Repl, + Run { + script: String, + }, + Test { + no_run: bool, + fail_fast: bool, + quiet: bool, + allow_none: bool, + include: Option>, + filter: Option, + }, + Types, + Upgrade { + dry_run: bool, + force: bool, + canary: bool, + version: Option, + output: Option, + ca_file: Option, + }, +} + +impl Default for DenoSubcommand { + fn default() -> DenoSubcommand { + DenoSubcommand::Repl + } +} + +fn deserialize_maybe_log_level<'de, D>(d: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + struct OptionalLogLevelVisitor; + impl<'de> de::Visitor<'de> for OptionalLogLevelVisitor { + type Value = Option; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "null or a valid log level string") + } + + fn visit_none(self) -> Result + where + E: de::Error, + { + Ok(None) + } + + fn visit_some(self, d: D) -> Result + 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(self, s: &str) -> Result + 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( + maybe_level: &Option, + s: S, +) -> Result +where + S: Serializer, +{ + match maybe_level { + None => s.serialize_none(), + Some(level) => s.serialize_str(&level.to_string()), + } +} diff --git a/cli/main.rs b/cli/main.rs index 7f6a80f30e1a1f..7fbb68d2f8b921 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -19,6 +19,7 @@ mod file_fetcher; mod file_watcher; mod flags; mod flags_allow_net; +mod flags_rt; mod fmt_errors; mod fs_util; mod http_cache; @@ -32,6 +33,7 @@ mod module_graph; mod module_loader; mod ops; mod program_state; +mod rt; mod source_maps; mod specifier_handler; mod standalone; @@ -1222,7 +1224,7 @@ pub fn main() { colors::enable_ansi(); // For Windows 10 let args: Vec = env::args().collect(); - if let Err(err) = standalone::try_run_standalone_binary(args.clone()) { + if let Err(err) = crate::rt::try_run_standalone_binary(args.clone()) { eprintln!("{}: {}", colors::red_bold("error"), err.to_string()); std::process::exit(1); } diff --git a/cli/rt.rs b/cli/rt.rs new file mode 100644 index 00000000000000..bd89b236dd5515 --- /dev/null +++ b/cli/rt.rs @@ -0,0 +1,198 @@ +// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. + +use crate::flags_rt::Flags; +use crate::version; +use deno_core::error::type_error; +use deno_core::error::AnyError; +use deno_core::error::Context; +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::ModuleSpecifier; +use deno_core::OpState; +use deno_runtime::colors; +use deno_runtime::permissions::Permissions; +use deno_runtime::tokio_util; +use deno_runtime::worker::MainWorker; +use deno_runtime::worker::WorkerOptions; +use std::cell::RefCell; +use std::convert::TryInto; +use std::env::current_exe; +use std::fs::File; +use std::io::Read; +use std::io::Seek; +use std::io::SeekFrom; +use std::iter::once; +use std::pin::Pin; +use std::rc::Rc; +use std::sync::Arc; + +#[derive(Deserialize, Serialize)] +pub(crate) struct Metadata { + pub(crate) flags: Flags, + pub(crate) ca_data: Option>, +} + +const MAGIC_TRAILER: &[u8; 8] = b"d3n0l4nd"; + +/// This function will try to run this binary as a standalone binary +/// produced by `deno compile`. It determines if this is a stanalone +/// binary by checking for the magic trailer string `D3N0` at EOF-12. +/// The magic trailer is followed by: +/// - a u64 pointer to the JS bundle embedded in the binary +/// - 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) -> Result<(), AnyError> { + let current_exe_path = current_exe()?; + + let mut current_exe = File::open(current_exe_path)?; + let trailer_pos = current_exe.seek(SeekFrom::End(-24))?; + let mut trailer = [0; 24]; + current_exe.read_exact(&mut trailer)?; + let (magic_trailer, rest) = trailer.split_at(8); + if magic_trailer == MAGIC_TRAILER { + let (bundle_pos, rest) = rest.split_at(8); + 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))?; + + let bundle = read_string_slice(&mut current_exe, bundle_pos, bundle_len) + .context("Failed to read source bundle from the current executable")?; + let metadata = + read_string_slice(&mut current_exe, metadata_pos, metadata_len) + .context("Failed to read metadata from the current executable")?; + + 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()); + std::process::exit(1); + } + std::process::exit(0); + } else { + Ok(()) + } +} + +fn u64_from_bytes(arr: &[u8]) -> Result { + 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 { + 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"; + +struct EmbeddedModuleLoader(String); + +impl ModuleLoader for EmbeddedModuleLoader { + fn resolve( + &self, + _op_state: Rc>, + specifier: &str, + _referrer: &str, + _is_main: bool, + ) -> Result { + if specifier != SPECIFIER { + return Err(type_error( + "Self-contained binaries don't support module loading", + )); + } + Ok(ModuleSpecifier::resolve_url(specifier)?) + } + + fn load( + &self, + _op_state: Rc>, + module_specifier: &ModuleSpecifier, + _maybe_referrer: Option, + _is_dynamic: bool, + ) -> Pin> { + let module_specifier = module_specifier.clone(); + let code = self.0.to_string(); + async move { + if module_specifier.to_string() != SPECIFIER { + return Err(type_error( + "Self-contained binaries don't support module loading", + )); + } + Ok(deno_core::ModuleSource { + code, + module_url_specified: module_specifier.to_string(), + module_url_found: module_specifier.to_string(), + }) + } + .boxed_local() + } +} + +async fn run(source_code: String, metadata: Metadata) -> Result<(), AnyError> { + let Metadata { flags, ca_data } = metadata; + let main_module = ModuleSpecifier::resolve_url(SPECIFIER)?; + let permissions = Permissions::from_options(&flags.clone().into()); + let module_loader = Rc::new(EmbeddedModuleLoader(source_code)); + let create_web_worker_cb = Arc::new(|_| { + 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::>(), + ); + // TODO(nayeemrmn): Unify this Flags -> WorkerOptions mapping with `deno run`. + let options = WorkerOptions { + apply_source_maps: false, + args: flags.argv.clone(), + debug_flag: flags.log_level.map_or(false, |l| l == log::Level::Debug), + user_agent: format!("Deno/{}", version::deno()), + unstable: flags.unstable, + ca_data, + seed: flags.seed, + js_error_create_fn: None, + create_web_worker_cb, + attach_inspector: false, + maybe_inspector_server: None, + should_break_on_first_statement: false, + module_loader, + runtime_version: version::deno(), + ts_version: version::TYPESCRIPT.to_string(), + no_color: !colors::use_color(), + get_error_class_fn: Some(&get_error_class_name), + }; + let mut worker = + MainWorker::from_options(main_module.clone(), permissions, &options); + worker.bootstrap(&options); + worker.execute_module(&main_module).await?; + worker.execute("window.dispatchEvent(new Event('load'))")?; + worker.run_event_loop().await?; + worker.execute("window.dispatchEvent(new Event('unload'))")?; + Ok(()) +} + +fn get_error_class_name(e: &AnyError) -> &'static str { + deno_runtime::errors::get_error_class_name(e).unwrap_or_else(|| { + panic!("Error '{}' contains boxed error of unknown type", e); + }) +} diff --git a/cli/standalone.rs b/cli/standalone.rs index 8379358a02cf4f..dccdb7cd0ea24d 100644 --- a/cli/standalone.rs +++ b/cli/standalone.rs @@ -1,199 +1,21 @@ -use crate::colors; -use crate::flags::DenoSubcommand; +// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. + use crate::flags::Flags; -use crate::tokio_util; -use crate::version; +use crate::flags_rt::DenoSubcommand; +use crate::rt::Metadata; use deno_core::error::bail; -use deno_core::error::type_error; use deno_core::error::AnyError; -use deno_core::error::Context; -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::ModuleSpecifier; -use deno_core::OpState; -use deno_runtime::permissions::Permissions; -use deno_runtime::worker::MainWorker; -use deno_runtime::worker::WorkerOptions; -use std::cell::RefCell; -use std::convert::TryInto; -use std::env::current_exe; use std::fs::read; use std::fs::File; use std::io::Read; use std::io::Seek; use std::io::SeekFrom; use std::io::Write; -use std::iter::once; use std::path::PathBuf; -use std::pin::Pin; -use std::rc::Rc; -use std::sync::Arc; - -#[derive(Deserialize, Serialize)] -struct Metadata { - flags: Flags, - ca_data: Option>, -} const MAGIC_TRAILER: &[u8; 8] = b"d3n0l4nd"; -/// This function will try to run this binary as a standalone binary -/// produced by `deno compile`. It determines if this is a stanalone -/// binary by checking for the magic trailer string `D3N0` at EOF-12. -/// The magic trailer is followed by: -/// - a u64 pointer to the JS bundle embedded in the binary -/// - 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) -> Result<(), AnyError> { - let current_exe_path = current_exe()?; - - let mut current_exe = File::open(current_exe_path)?; - let trailer_pos = current_exe.seek(SeekFrom::End(-24))?; - let mut trailer = [0; 24]; - current_exe.read_exact(&mut trailer)?; - let (magic_trailer, rest) = trailer.split_at(8); - if magic_trailer == MAGIC_TRAILER { - let (bundle_pos, rest) = rest.split_at(8); - 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))?; - - let bundle = read_string_slice(&mut current_exe, bundle_pos, bundle_len) - .context("Failed to read source bundle from the current executable")?; - let metadata = - read_string_slice(&mut current_exe, metadata_pos, metadata_len) - .context("Failed to read metadata from the current executable")?; - - 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()); - std::process::exit(1); - } - std::process::exit(0); - } else { - Ok(()) - } -} - -fn u64_from_bytes(arr: &[u8]) -> Result { - 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 { - 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"; - -struct EmbeddedModuleLoader(String); - -impl ModuleLoader for EmbeddedModuleLoader { - fn resolve( - &self, - _op_state: Rc>, - specifier: &str, - _referrer: &str, - _is_main: bool, - ) -> Result { - if specifier != SPECIFIER { - return Err(type_error( - "Self-contained binaries don't support module loading", - )); - } - Ok(ModuleSpecifier::resolve_url(specifier)?) - } - - fn load( - &self, - _op_state: Rc>, - module_specifier: &ModuleSpecifier, - _maybe_referrer: Option, - _is_dynamic: bool, - ) -> Pin> { - let module_specifier = module_specifier.clone(); - let code = self.0.to_string(); - async move { - if module_specifier.to_string() != SPECIFIER { - return Err(type_error( - "Self-contained binaries don't support module loading", - )); - } - Ok(deno_core::ModuleSource { - code, - module_url_specified: module_specifier.to_string(), - module_url_found: module_specifier.to_string(), - }) - } - .boxed_local() - } -} - -async fn run(source_code: String, metadata: Metadata) -> Result<(), AnyError> { - let Metadata { flags, ca_data } = metadata; - let main_module = ModuleSpecifier::resolve_url(SPECIFIER)?; - let permissions = Permissions::from_options(&flags.clone().into()); - let module_loader = Rc::new(EmbeddedModuleLoader(source_code)); - let create_web_worker_cb = Arc::new(|_| { - 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::>(), - ); - // TODO(nayeemrmn): Unify this Flags -> WorkerOptions mapping with `deno run`. - let options = WorkerOptions { - apply_source_maps: false, - args: flags.argv.clone(), - debug_flag: flags.log_level.map_or(false, |l| l == log::Level::Debug), - user_agent: crate::http_util::get_user_agent(), - unstable: flags.unstable, - ca_data, - seed: flags.seed, - js_error_create_fn: None, - create_web_worker_cb, - attach_inspector: false, - maybe_inspector_server: None, - should_break_on_first_statement: false, - module_loader, - runtime_version: version::deno(), - ts_version: version::TYPESCRIPT.to_string(), - no_color: !colors::use_color(), - get_error_class_fn: Some(&crate::errors::get_error_class_name), - }; - let mut worker = - MainWorker::from_options(main_module.clone(), permissions, &options); - worker.bootstrap(&options); - worker.execute_module(&main_module).await?; - worker.execute("window.dispatchEvent(new Event('load'))")?; - worker.run_event_loop().await?; - worker.execute("window.dispatchEvent(new Event('unload'))")?; - Ok(()) -} - /// This functions creates a standalone deno binary by appending a bundle /// and magic trailer to the currently executing binary. pub async fn create_standalone_binary( diff --git a/cli/version.rs b/cli/version.rs index 49cb34f1d903c9..21637f2500b07a 100644 --- a/cli/version.rs +++ b/cli/version.rs @@ -10,6 +10,7 @@ pub fn deno() -> String { }) } +#[allow(dead_code)] pub fn is_canary() -> bool { option_env!("DENO_CANARY").is_some() } diff --git a/test_util/src/lib.rs b/test_util/src/lib.rs index 262084af72909d..1e6d64ad31a77d 100644 --- a/test_util/src/lib.rs +++ b/test_util/src/lib.rs @@ -106,6 +106,15 @@ pub fn deno_exe_path() -> PathBuf { p } +pub fn denort_exe_path() -> PathBuf { + // Something like /Users/rld/src/deno/target/debug/deps/deno + let mut p = target_dir().join("denort"); + if cfg!(windows) { + p.set_extension("exe"); + } + p +} + pub fn prebuilt_tool_path(tool: &str) -> PathBuf { let mut exe = tool.to_string(); exe.push_str(if cfg!(windows) { ".exe" } else { "" });