diff options
Diffstat (limited to 'cli/main.rs')
-rw-r--r-- | cli/main.rs | 196 |
1 files changed, 140 insertions, 56 deletions
diff --git a/cli/main.rs b/cli/main.rs index 6c48a75f6..b4e1f1d2c 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -39,6 +39,7 @@ mod resolve_addr; mod signal; mod source_maps; mod specifier_handler; +mod standalone; mod text_encoding; mod tokio_util; mod tools; @@ -51,10 +52,16 @@ mod worker; use crate::file_fetcher::File; use crate::file_fetcher::FileFetcher; use crate::file_watcher::ModuleResolutionResult; +use crate::flags::DenoSubcommand; +use crate::flags::Flags; +use crate::import_map::ImportMap; use crate::media_type::MediaType; use crate::permissions::Permissions; +use crate::program_state::exit_unstable; use crate::program_state::ProgramState; use crate::specifier_handler::FetchHandler; +use crate::standalone::create_standalone_binary; +use crate::tools::installer::infer_name_from_url; use crate::worker::MainWorker; use deno_core::error::generic_error; use deno_core::error::AnyError; @@ -66,12 +73,8 @@ use deno_core::v8_set_flags; use deno_core::ModuleSpecifier; use deno_doc as doc; use deno_doc::parser::DocFileLoader; -use flags::DenoSubcommand; -use flags::Flags; -use import_map::ImportMap; use log::Level; use log::LevelFilter; -use program_state::exit_unstable; use std::cell::RefCell; use std::env; use std::io::Read; @@ -149,6 +152,56 @@ fn get_types(unstable: bool) -> String { types } +async fn compile_command( + flags: Flags, + source_file: String, + out_file: Option<String>, +) -> Result<(), AnyError> { + if !flags.unstable { + exit_unstable("compile"); + } + + let debug = flags.log_level == Some(log::Level::Debug); + + let module_specifier = ModuleSpecifier::resolve_url_or_path(&source_file)?; + let program_state = ProgramState::new(flags.clone())?; + + let out_file = + out_file.or_else(|| infer_name_from_url(module_specifier.as_url())); + let out_file = match out_file { + Some(out_file) => out_file, + None => return Err(generic_error( + "An executable name was not provided. One could not be inferred from the URL. Aborting.", + )), + }; + + let module_graph = create_module_graph_and_maybe_check( + module_specifier.clone(), + program_state.clone(), + debug, + ) + .await?; + + info!( + "{} {}", + colors::green("Bundle"), + module_specifier.to_string() + ); + let bundle_str = bundle_module_graph(module_graph, flags, debug)?; + + info!( + "{} {}", + colors::green("Compile"), + module_specifier.to_string() + ); + create_standalone_binary(bundle_str.as_bytes().to_vec(), out_file.clone()) + .await?; + + info!("{} {}", colors::green("Emit"), out_file); + + Ok(()) +} + async fn info_command( flags: Flags, maybe_specifier: Option<String>, @@ -299,6 +352,73 @@ async fn eval_command( Ok(()) } +async fn create_module_graph_and_maybe_check( + module_specifier: ModuleSpecifier, + program_state: Arc<ProgramState>, + debug: bool, +) -> Result<module_graph::Graph, AnyError> { + let handler = Rc::new(RefCell::new(FetchHandler::new( + &program_state, + // when bundling, dynamic imports are only access for their type safety, + // therefore we will allow the graph to access any module. + Permissions::allow_all(), + )?)); + let mut builder = module_graph::GraphBuilder::new( + handler, + program_state.maybe_import_map.clone(), + program_state.lockfile.clone(), + ); + builder.add(&module_specifier, false).await?; + let module_graph = builder.get_graph(); + + if !program_state.flags.no_check { + // TODO(@kitsonk) support bundling for workers + let lib = if program_state.flags.unstable { + module_graph::TypeLib::UnstableDenoWindow + } else { + module_graph::TypeLib::DenoWindow + }; + let result_info = + module_graph.clone().check(module_graph::CheckOptions { + debug, + emit: false, + lib, + maybe_config_path: program_state.flags.config_path.clone(), + reload: program_state.flags.reload, + })?; + + debug!("{}", result_info.stats); + if let Some(ignored_options) = result_info.maybe_ignored_options { + eprintln!("{}", ignored_options); + } + if !result_info.diagnostics.is_empty() { + return Err(generic_error(result_info.diagnostics.to_string())); + } + } + + Ok(module_graph) +} + +fn bundle_module_graph( + module_graph: module_graph::Graph, + flags: Flags, + debug: bool, +) -> Result<String, AnyError> { + let (bundle, stats, maybe_ignored_options) = + module_graph.bundle(module_graph::BundleOptions { + debug, + maybe_config_path: flags.config_path, + })?; + match maybe_ignored_options { + Some(ignored_options) if flags.no_check => { + eprintln!("{}", ignored_options); + } + _ => {} + } + debug!("{}", stats); + Ok(bundle) +} + async fn bundle_command( flags: Flags, source_file: String, @@ -323,44 +443,12 @@ async fn bundle_command( module_specifier.to_string() ); - let handler = Rc::new(RefCell::new(FetchHandler::new( - &program_state, - // when bundling, dynamic imports are only access for their type safety, - // therefore we will allow the graph to access any module. - Permissions::allow_all(), - )?)); - let mut builder = module_graph::GraphBuilder::new( - handler, - program_state.maybe_import_map.clone(), - program_state.lockfile.clone(), - ); - builder.add(&module_specifier, false).await?; - let module_graph = builder.get_graph(); - - if !flags.no_check { - // TODO(@kitsonk) support bundling for workers - let lib = if flags.unstable { - module_graph::TypeLib::UnstableDenoWindow - } else { - module_graph::TypeLib::DenoWindow - }; - let result_info = - module_graph.clone().check(module_graph::CheckOptions { - debug, - emit: false, - lib, - maybe_config_path: flags.config_path.clone(), - reload: flags.reload, - })?; - - debug!("{}", result_info.stats); - if let Some(ignored_options) = result_info.maybe_ignored_options { - eprintln!("{}", ignored_options); - } - if !result_info.diagnostics.is_empty() { - return Err(generic_error(result_info.diagnostics.to_string())); - } - } + let module_graph = create_module_graph_and_maybe_check( + module_specifier, + program_state.clone(), + debug, + ) + .await?; let mut paths_to_watch: Vec<PathBuf> = module_graph .get_modules() @@ -392,19 +480,7 @@ async fn bundle_command( let flags = flags.clone(); let out_file = out_file.clone(); async move { - let (output, stats, maybe_ignored_options) = - module_graph.bundle(module_graph::BundleOptions { - debug, - maybe_config_path: flags.config_path, - })?; - - match maybe_ignored_options { - Some(ignored_options) if flags.no_check => { - eprintln!("{}", ignored_options); - } - _ => {} - } - debug!("{}", stats); + let output = bundle_module_graph(module_graph, flags, debug)?; debug!(">>>>> bundle END"); @@ -898,6 +974,10 @@ fn get_subcommand( DenoSubcommand::Cache { files } => { cache_command(flags, files).boxed_local() } + DenoSubcommand::Compile { + source_file, + out_file, + } => compile_command(flags, source_file, out_file).boxed_local(), DenoSubcommand::Fmt { check, files, @@ -968,8 +1048,12 @@ pub fn main() { colors::enable_ansi(); // For Windows 10 let args: Vec<String> = env::args().collect(); - let flags = flags::flags_from_vec(args); + if let Err(err) = standalone::try_run_standalone_binary(args.clone()) { + eprintln!("{}: {}", colors::red_bold("error"), err.to_string()); + std::process::exit(1); + } + let flags = flags::flags_from_vec(args); if let Some(ref v8_flags) = flags.v8_flags { init_v8_flags(v8_flags); } |