summaryrefslogtreecommitdiff
path: root/cli/lib.rs
diff options
context:
space:
mode:
authorRyan Dahl <ry@tinyclouds.org>2019-09-16 21:05:14 -0400
committerGitHub <noreply@github.com>2019-09-16 21:05:14 -0400
commit9cfdc60a23e6418d4780dc3ebd6266248555bb03 (patch)
tree19ca25fa733318024d1f36724a2c20741e649012 /cli/lib.rs
parent02cb34d8ad320360c800b9af7b941990c48b9742 (diff)
Move integration tests to //cli/tests/ (#2964)
This ensures the deno executable is properly created before running the integration tests. Also allows deno_cli to be used as a lib. Docs are now properly generated: https://docs.rs/deno_cli/0.18.4/deno_cli/ Towards #2933 Prep for #2955
Diffstat (limited to 'cli/lib.rs')
-rw-r--r--cli/lib.rs437
1 files changed, 437 insertions, 0 deletions
diff --git a/cli/lib.rs b/cli/lib.rs
new file mode 100644
index 000000000..ff8f02239
--- /dev/null
+++ b/cli/lib.rs
@@ -0,0 +1,437 @@
+// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
+#[macro_use]
+extern crate lazy_static;
+#[macro_use]
+extern crate log;
+#[macro_use]
+extern crate futures;
+#[macro_use]
+extern crate serde_json;
+extern crate clap;
+extern crate deno;
+extern crate deno_cli_snapshots;
+extern crate indexmap;
+#[cfg(unix)]
+extern crate nix;
+extern crate rand;
+extern crate serde;
+extern crate serde_derive;
+extern crate url;
+
+pub mod colors;
+pub mod compilers;
+pub mod deno_dir;
+pub mod deno_error;
+pub mod diagnostics;
+mod disk_cache;
+mod file_fetcher;
+pub mod flags;
+pub mod fmt_errors;
+mod fs;
+mod global_timer;
+mod http_body;
+mod http_util;
+mod import_map;
+pub mod msg;
+pub mod ops;
+pub mod permissions;
+mod progress;
+mod repl;
+pub mod resolve_addr;
+pub mod resources;
+mod shell;
+mod signal;
+pub mod source_maps;
+mod startup_data;
+pub mod state;
+mod tokio_read;
+mod tokio_util;
+mod tokio_write;
+pub mod version;
+pub mod worker;
+
+use crate::progress::Progress;
+use crate::state::ThreadSafeState;
+use crate::worker::Worker;
+use deno::v8_set_flags;
+use deno::ErrBox;
+use deno::ModuleSpecifier;
+use flags::DenoFlags;
+use flags::DenoSubcommand;
+use futures::lazy;
+use futures::Future;
+use log::Level;
+use log::Metadata;
+use log::Record;
+use std::env;
+
+static LOGGER: Logger = Logger;
+
+struct Logger;
+
+impl log::Log for Logger {
+ fn enabled(&self, metadata: &Metadata) -> bool {
+ metadata.level() <= log::max_level()
+ }
+
+ fn log(&self, record: &Record) {
+ if self.enabled(record.metadata()) {
+ let mut target = record.target().to_string();
+
+ if let Some(line_no) = record.line() {
+ target.push_str(":");
+ target.push_str(&line_no.to_string());
+ }
+
+ println!("{} RS - {} - {}", record.level(), target, record.args());
+ }
+ }
+ fn flush(&self) {}
+}
+
+fn print_err_and_exit(err: ErrBox) {
+ eprintln!("{}", err.to_string());
+ std::process::exit(1);
+}
+
+fn js_check(r: Result<(), ErrBox>) {
+ if let Err(err) = r {
+ print_err_and_exit(err);
+ }
+}
+
+fn create_worker_and_state(
+ flags: DenoFlags,
+ argv: Vec<String>,
+) -> (Worker, ThreadSafeState) {
+ use crate::shell::Shell;
+ use std::sync::Arc;
+ use std::sync::Mutex;
+ let shell = Arc::new(Mutex::new(Shell::new()));
+ let progress = Progress::new();
+ progress.set_callback(move |_done, _completed, _total, status, msg| {
+ if !status.is_empty() {
+ let mut s = shell.lock().unwrap();
+ s.status(status, msg).expect("shell problem");
+ }
+ });
+ // TODO(kevinkassimo): maybe make include_deno_namespace also configurable?
+ let state = ThreadSafeState::new(flags, argv, progress, true)
+ .map_err(print_err_and_exit)
+ .unwrap();
+ let worker = Worker::new(
+ "main".to_string(),
+ startup_data::deno_isolate_init(),
+ state.clone(),
+ );
+
+ (worker, state)
+}
+
+fn types_command() {
+ let content = deno_cli_snapshots::get_asset("lib.deno_runtime.d.ts").unwrap();
+ println!("{}", content);
+}
+
+fn print_cache_info(worker: Worker) {
+ let state = worker.state;
+
+ println!(
+ "{} {:?}",
+ colors::bold("DENO_DIR location:".to_string()),
+ state.dir.root
+ );
+ println!(
+ "{} {:?}",
+ colors::bold("Remote modules cache:".to_string()),
+ state.dir.deps_cache.location
+ );
+ println!(
+ "{} {:?}",
+ colors::bold("TypeScript compiler cache:".to_string()),
+ state.dir.gen_cache.location
+ );
+}
+
+pub fn print_file_info(
+ worker: Worker,
+ module_specifier: &ModuleSpecifier,
+) -> impl Future<Item = Worker, Error = ()> {
+ let state_ = worker.state.clone();
+ let module_specifier_ = module_specifier.clone();
+
+ state_
+ .file_fetcher
+ .fetch_source_file_async(&module_specifier)
+ .map_err(|err| println!("{}", err))
+ .and_then(|out| {
+ println!(
+ "{} {}",
+ colors::bold("local:".to_string()),
+ out.filename.to_str().unwrap()
+ );
+
+ println!(
+ "{} {}",
+ colors::bold("type:".to_string()),
+ msg::enum_name_media_type(out.media_type)
+ );
+
+ state_
+ .clone()
+ .fetch_compiled_module(&module_specifier_)
+ .map_err(|e| {
+ debug!("compiler error exiting!");
+ eprintln!("\n{}", e.to_string());
+ std::process::exit(1);
+ })
+ .and_then(move |compiled| {
+ if out.media_type == msg::MediaType::TypeScript
+ || (out.media_type == msg::MediaType::JavaScript
+ && state_.ts_compiler.compile_js)
+ {
+ let compiled_source_file = state_
+ .ts_compiler
+ .get_compiled_source_file(&out.url)
+ .unwrap();
+
+ println!(
+ "{} {}",
+ colors::bold("compiled:".to_string()),
+ compiled_source_file.filename.to_str().unwrap(),
+ );
+ }
+
+ if let Ok(source_map) = state_
+ .clone()
+ .ts_compiler
+ .get_source_map_file(&module_specifier_)
+ {
+ println!(
+ "{} {}",
+ colors::bold("map:".to_string()),
+ source_map.filename.to_str().unwrap()
+ );
+ }
+
+ if let Some(deps) =
+ worker.state.modules.lock().unwrap().deps(&compiled.name)
+ {
+ println!("{}{}", colors::bold("deps:\n".to_string()), deps.name);
+ if let Some(ref depsdeps) = deps.deps {
+ for d in depsdeps {
+ println!("{}", d);
+ }
+ }
+ } else {
+ println!(
+ "{} cannot retrieve full dependency graph",
+ colors::bold("deps:".to_string()),
+ );
+ }
+ Ok(worker)
+ })
+ })
+}
+
+fn info_command(flags: DenoFlags, argv: Vec<String>) {
+ let (mut worker, state) = create_worker_and_state(flags, argv.clone());
+
+ // If it was just "deno info" print location of caches and exit
+ if argv.len() == 1 {
+ return print_cache_info(worker);
+ }
+
+ let main_module = state.main_module().unwrap();
+ let main_future = lazy(move || {
+ // Setup runtime.
+ js_check(worker.execute("denoMain()"));
+ debug!("main_module {}", main_module);
+
+ worker
+ .execute_mod_async(&main_module, true)
+ .map_err(print_err_and_exit)
+ .and_then(move |()| print_file_info(worker, &main_module))
+ .and_then(|worker| {
+ worker.then(|result| {
+ js_check(result);
+ Ok(())
+ })
+ })
+ });
+ tokio_util::run(main_future);
+}
+
+fn fetch_command(flags: DenoFlags, argv: Vec<String>) {
+ let (mut worker, state) = create_worker_and_state(flags, argv.clone());
+
+ let main_module = state.main_module().unwrap();
+ let main_future = lazy(move || {
+ // Setup runtime.
+ js_check(worker.execute("denoMain()"));
+ debug!("main_module {}", main_module);
+
+ worker.execute_mod_async(&main_module, true).then(|result| {
+ js_check(result);
+ Ok(())
+ })
+ });
+ tokio_util::run(main_future);
+}
+
+fn eval_command(flags: DenoFlags, argv: Vec<String>) {
+ let (mut worker, state) = create_worker_and_state(flags, argv);
+ // Wrap provided script in async function so asynchronous methods
+ // work. This is required until top-level await is not supported.
+ let js_source = format!(
+ "async function _topLevelWrapper(){{
+ {}
+ }}
+ _topLevelWrapper();
+ ",
+ &state.argv[1]
+ );
+
+ let main_future = lazy(move || {
+ js_check(worker.execute("denoMain()"));
+ // ATM imports in `deno eval` are not allowed
+ // TODO Support ES modules once Worker supports evaluating anonymous modules.
+ js_check(worker.execute(&js_source));
+ worker.then(|result| {
+ js_check(result);
+ Ok(())
+ })
+ });
+ tokio_util::run(main_future);
+}
+
+fn xeval_command(flags: DenoFlags, argv: Vec<String>) {
+ let xeval_replvar = flags.xeval_replvar.clone().unwrap();
+ let (mut worker, state) = create_worker_and_state(flags, argv);
+ let xeval_source = format!(
+ "window._xevalWrapper = async function ({}){{
+ {}
+ }}",
+ &xeval_replvar, &state.argv[1]
+ );
+
+ let main_future = lazy(move || {
+ // Setup runtime.
+ js_check(worker.execute(&xeval_source));
+ js_check(worker.execute("denoMain()"));
+ worker
+ .then(|result| {
+ js_check(result);
+ Ok(())
+ })
+ .map_err(print_err_and_exit)
+ });
+ tokio_util::run(main_future);
+}
+
+fn bundle_command(flags: DenoFlags, argv: Vec<String>) {
+ let (mut _worker, state) = create_worker_and_state(flags, argv);
+
+ let main_module = state.main_module().unwrap();
+ assert!(state.argv.len() >= 3);
+ let out_file = state.argv[2].clone();
+ debug!(">>>>> bundle_async START");
+ let bundle_future = state
+ .ts_compiler
+ .bundle_async(state.clone(), main_module.to_string(), out_file)
+ .map_err(|err| {
+ debug!("diagnostics returned, exiting!");
+ eprintln!("");
+ print_err_and_exit(err);
+ })
+ .and_then(move |_| {
+ debug!(">>>>> bundle_async END");
+ Ok(())
+ });
+ tokio_util::run(bundle_future);
+}
+
+fn run_repl(flags: DenoFlags, argv: Vec<String>) {
+ let (mut worker, _state) = create_worker_and_state(flags, argv);
+
+ // REPL situation.
+ let main_future = lazy(move || {
+ // Setup runtime.
+ js_check(worker.execute("denoMain()"));
+ worker
+ .then(|result| {
+ js_check(result);
+ Ok(())
+ })
+ .map_err(|(err, _worker): (ErrBox, Worker)| print_err_and_exit(err))
+ });
+ tokio_util::run(main_future);
+}
+
+fn run_script(flags: DenoFlags, argv: Vec<String>) {
+ let use_current_thread = flags.current_thread;
+ let (mut worker, state) = create_worker_and_state(flags, argv);
+
+ let main_module = state.main_module().unwrap();
+ // Normal situation of executing a module.
+ let main_future = lazy(move || {
+ // Setup runtime.
+ js_check(worker.execute("denoMain()"));
+ debug!("main_module {}", main_module);
+
+ worker
+ .execute_mod_async(&main_module, false)
+ .and_then(move |()| {
+ js_check(worker.execute("window.dispatchEvent(new Event('load'))"));
+ worker.then(|result| {
+ js_check(result);
+ Ok(())
+ })
+ })
+ .map_err(print_err_and_exit)
+ });
+
+ if use_current_thread {
+ tokio_util::run_on_current_thread(main_future);
+ } else {
+ tokio_util::run(main_future);
+ }
+}
+
+fn version_command() {
+ println!("deno: {}", version::DENO);
+ println!("v8: {}", version::v8());
+ println!("typescript: {}", version::TYPESCRIPT);
+}
+
+pub fn main() {
+ #[cfg(windows)]
+ ansi_term::enable_ansi_support().ok(); // For Windows 10
+
+ log::set_logger(&LOGGER).unwrap();
+ let args: Vec<String> = env::args().collect();
+ let (flags, subcommand, argv) = flags::flags_from_vec(args);
+
+ if let Some(ref v8_flags) = flags.v8_flags {
+ v8_set_flags(v8_flags.clone());
+ }
+
+ let log_level = match flags.log_level {
+ Some(level) => level,
+ None => Level::Warn,
+ };
+ log::set_max_level(log_level.to_level_filter());
+
+ match subcommand {
+ DenoSubcommand::Bundle => bundle_command(flags, argv),
+ DenoSubcommand::Completions => {}
+ DenoSubcommand::Eval => eval_command(flags, argv),
+ DenoSubcommand::Fetch => fetch_command(flags, argv),
+ DenoSubcommand::Info => info_command(flags, argv),
+ DenoSubcommand::Repl => run_repl(flags, argv),
+ DenoSubcommand::Run => run_script(flags, argv),
+ DenoSubcommand::Types => types_command(),
+ DenoSubcommand::Version => version_command(),
+ DenoSubcommand::Xeval => xeval_command(flags, argv),
+ }
+}