From 99ce807a121efdbbee784409094c1596299d90de Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Fri, 8 Feb 2019 21:36:10 -0500 Subject: [PATCH] Add deps to --info output. (#1720) Move module stuff into its own file. --- src/deno_dir.rs | 22 ----- src/isolate.rs | 73 +++++----------- src/main.rs | 18 ++-- src/modules.rs | 183 ++++++++++++++++++++++++++++++++++++++++ tests/022_info_flag.out | 2 + 5 files changed, 216 insertions(+), 82 deletions(-) create mode 100644 src/modules.rs diff --git a/src/deno_dir.rs b/src/deno_dir.rs index a6a6d0b6c1..b074c0458c 100644 --- a/src/deno_dir.rs +++ b/src/deno_dir.rs @@ -447,28 +447,6 @@ impl DenoDir { debug!("module_name: {}, filename: {}", module_name, filename); Ok((module_name, filename)) } - - pub fn print_file_info(self: &Self, filename: String) { - let maybe_out = self.code_fetch(&filename, "."); - if maybe_out.is_err() { - println!("{}", maybe_out.unwrap_err()); - return; - } - let out = maybe_out.unwrap(); - - println!("local: {}", &(out.filename)); - println!("type: {}", msg::enum_name_media_type(out.media_type)); - if out.maybe_output_code_filename.is_some() { - println!( - "compiled: {}", - out.maybe_output_code_filename.as_ref().unwrap(), - ); - } - if out.maybe_source_map_filename.is_some() { - println!("map: {}", out.maybe_source_map_filename.as_ref().unwrap()); - } - // TODO print deps. - } } impl SourceMapGetter for DenoDir { diff --git a/src/isolate.rs b/src/isolate.rs index fbe65a54e5..20733c876a 100644 --- a/src/isolate.rs +++ b/src/isolate.rs @@ -14,17 +14,17 @@ use crate::errors::RustOrJsError; use crate::flags; use crate::js_errors::JSError; use crate::libdeno; +use crate::modules::Modules; use crate::msg; use crate::permissions::DenoPermissions; use crate::tokio_util; - use futures::sync::mpsc as async_mpsc; use futures::Future; use libc::c_char; use libc::c_void; use std; use std::cell::Cell; -use std::collections::HashMap; +use std::cell::RefCell; use std::env; use std::ffi::CStr; use std::ffi::CString; @@ -52,10 +52,6 @@ pub type Dispatch = fn(isolate: &Isolate, buf: libdeno::deno_buf, data_buf: libdeno::deno_buf) -> (bool, Box); -pub struct ModuleInfo { - name: String, -} - pub struct Isolate { libdeno_isolate: *const libdeno::isolate, dispatch: Dispatch, @@ -63,8 +59,7 @@ pub struct Isolate { tx: mpsc::Sender<(i32, Buf)>, ntasks: Cell, timeout_due: Cell>, - pub modules: HashMap, - pub modules_by_name: HashMap, + pub modules: RefCell, pub state: Arc, } @@ -202,8 +197,7 @@ impl Isolate { tx, ntasks: Cell::new(0), timeout_due: Cell::new(None), - modules: HashMap::new(), - modules_by_name: HashMap::new(), + modules: RefCell::new(Modules::new()), state, } } @@ -290,49 +284,11 @@ impl Isolate { return Err(js_error); } - let name2 = name.clone(); - self.modules.insert(id, ModuleInfo { name }); - - debug!("modules_by_name insert {}", name2); - self.modules_by_name.insert(name2, id); + self.modules.borrow_mut().register(id, &name); Ok(id) } - // TODO(ry) This should be private... - pub fn resolve_cb( - &self, - specifier: &str, - referrer: libdeno::deno_mod, - ) -> libdeno::deno_mod { - self - .state - .metrics - .resolve_count - .fetch_add(1, Ordering::Relaxed); - - debug!("resolve_cb {}", specifier); - - let r = self.modules.get(&referrer); - if r.is_none() { - debug!("cant find referrer {}", referrer); - return 0; - } - let referrer_name = &r.unwrap().name; - let r = self.state.dir.resolve_module(specifier, referrer_name); - if let Err(err) = r { - debug!("potentially swallowed err: {}", err); - return 0; - } - let (name, _local_filename) = r.unwrap(); - - if let Some(id) = self.modules_by_name.get(&name) { - return *id; - } else { - return 0; - } - } - // TODO(ry) make this return a future. pub fn mod_load_deps( &mut self, @@ -340,8 +296,8 @@ impl Isolate { ) -> Result<(), RustOrJsError> { // basically iterate over the imports, start loading them. - let referrer = &self.modules[&id]; - let referrer_name = referrer.name.clone(); + let referrer_name = + { self.modules.borrow_mut().get_name(id).unwrap().clone() }; let len = unsafe { libdeno::deno_mod_imports_len(self.libdeno_isolate, id) }; @@ -366,7 +322,7 @@ impl Isolate { debug!("mod_load_deps {} {}", i, name); - if None == self.modules_by_name.get(&name) { + if !self.modules.borrow_mut().is_registered(&name) { let out = code_fetch_and_maybe_compile(&self.state, specifier, &referrer_name)?; let child_id = @@ -415,7 +371,7 @@ impl Isolate { .map_err(RustOrJsError::from)?; let id = self - .mod_new(out.filename.clone(), out.js_source()) + .mod_new(out.module_name.clone(), out.js_source()) .map_err(RustOrJsError::from)?; self.mod_load_deps(id)?; @@ -539,7 +495,16 @@ extern "C" fn resolve_cb( let isolate = unsafe { Isolate::from_raw_ptr(user_data) }; let specifier_c: &CStr = unsafe { CStr::from_ptr(specifier_ptr) }; let specifier: &str = specifier_c.to_str().unwrap(); - isolate.resolve_cb(specifier, referrer) + isolate + .state + .metrics + .resolve_count + .fetch_add(1, Ordering::Relaxed); + isolate.modules.borrow_mut().resolve_cb( + &isolate.state.dir, + specifier, + referrer, + ) } // Dereferences the C pointer into the Rust Isolate object. diff --git a/src/main.rs b/src/main.rs index 25e68e3443..d3ec4b721b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,6 +19,7 @@ mod http_util; pub mod isolate; pub mod js_errors; pub mod libdeno; +pub mod modules; pub mod msg; pub mod msg_util; pub mod ops; @@ -90,7 +91,7 @@ fn main() { flags.allow_write = true; } - let should_prefetch = flags.prefetch; + let should_prefetch = flags.prefetch || flags.info; let should_display_info = flags.info; let state = Arc::new(isolate::IsolateState::new(flags, rest_argv, None)); @@ -107,14 +108,19 @@ fn main() { // Execute input file. if isolate.state.argv.len() > 1 { let input_filename = isolate.state.argv[1].clone(); - if should_display_info { - // Display file info and exit. Do not run file - isolate.state.dir.print_file_info(input_filename); - std::process::exit(0); - } isolate .execute_mod(&input_filename, should_prefetch) .unwrap_or_else(print_err_and_exit); + + if should_display_info { + // Display file info and exit. Do not run file + modules::print_file_info( + &isolate.modules.borrow(), + &isolate.state.dir, + input_filename, + ); + std::process::exit(0); + } } isolate diff --git a/src/modules.rs b/src/modules.rs new file mode 100644 index 0000000000..7711dec951 --- /dev/null +++ b/src/modules.rs @@ -0,0 +1,183 @@ +// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. +use crate::ansi; +use crate::deno_dir::DenoDir; +use crate::libdeno::deno_mod; +use crate::msg; +use std::collections::HashMap; +use std::collections::HashSet; +use std::fmt; + +pub struct ModuleInfo { + name: String, + children: Vec, +} + +/// A collection of JS modules. +#[derive(Default)] +pub struct Modules { + pub info: HashMap, + pub by_name: HashMap, +} + +impl Modules { + pub fn new() -> Modules { + Self { + info: HashMap::new(), + by_name: HashMap::new(), + } + } + + pub fn get_id(&self, name: &str) -> Option { + self.by_name.get(name).cloned() + } + + pub fn get_children(&self, id: deno_mod) -> Option<&Vec> { + self.info.get(&id).map(|i| &i.children) + } + + pub fn get_name(&self, id: deno_mod) -> Option<&String> { + self.info.get(&id).map(|i| &i.name) + } + + pub fn is_registered(&self, name: &str) -> bool { + self.by_name.get(name).is_some() + } + + pub fn register(&mut self, id: deno_mod, name: &str) { + let name = String::from(name); + debug!("register {}", name); + self.by_name.insert(name.clone(), id); + self.info.insert( + id, + ModuleInfo { + name, + children: Vec::new(), + }, + ); + } + + pub fn resolve_cb( + &mut self, + deno_dir: &DenoDir, + specifier: &str, + referrer: deno_mod, + ) -> deno_mod { + debug!("resolve_cb {}", specifier); + + let maybe_info = self.info.get_mut(&referrer); + if maybe_info.is_none() { + debug!("cant find referrer {}", referrer); + return 0; + } + let info = maybe_info.unwrap(); + let referrer_name = &info.name; + let r = deno_dir.resolve_module(specifier, referrer_name); + if let Err(err) = r { + debug!("potentially swallowed err: {}", err); + return 0; + } + let (name, _local_filename) = r.unwrap(); + + if let Some(id) = self.by_name.get(&name) { + let child_id = *id; + info.children.push(child_id); + return child_id; + } else { + return 0; + } + } +} + +pub struct Deps { + pub name: String, + pub deps: Option>, + depth: usize, +} + +impl Deps { + pub fn new(modules: &Modules, module_name: &str) -> Deps { + let mut seen = HashSet::new(); + let id = modules.get_id(module_name).unwrap(); + Self::helper(&mut seen, 0, modules, id) + } + + fn helper( + seen: &mut HashSet, + depth: usize, + modules: &Modules, + id: deno_mod, + ) -> Deps { + let name = modules.get_name(id).unwrap().to_string(); + if seen.contains(&id) { + Deps { + name, + depth, + deps: None, + } + } else { + seen.insert(id); + let child_ids = modules.get_children(id).unwrap(); + let deps = child_ids + .iter() + .map(|dep_id| Self::helper(seen, depth + 1, modules, *dep_id)) + .collect(); + Deps { + name, + depth, + deps: Some(deps), + } + } + } +} + +impl fmt::Display for Deps { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + for _i in 0..self.depth { + write!(f, "| ")?; + } + write!(f, "{}", self.name)?; + if let Some(ref deps) = self.deps { + for d in deps { + write!(f, "\n{}", d)?; + } + } + Ok(()) + } +} + +pub fn print_file_info( + modules: &Modules, + deno_dir: &DenoDir, + filename: String, +) { + let maybe_out = deno_dir.code_fetch(&filename, "."); + if maybe_out.is_err() { + println!("{}", maybe_out.unwrap_err()); + return; + } + let out = maybe_out.unwrap(); + + println!("{} {}", ansi::bold("local:".to_string()), &(out.filename)); + println!( + "{} {}", + ansi::bold("type:".to_string()), + msg::enum_name_media_type(out.media_type) + ); + if out.maybe_output_code_filename.is_some() { + println!( + "{} {}", + ansi::bold("compiled:".to_string()), + out.maybe_output_code_filename.as_ref().unwrap(), + ); + } + if out.maybe_source_map_filename.is_some() { + println!( + "{} {}", + ansi::bold("map:".to_string()), + out.maybe_source_map_filename.as_ref().unwrap() + ); + } + + let deps = Deps::new(modules, &out.module_name); + println!("{} {}", ansi::bold("deps:".to_string()), deps); +} diff --git a/tests/022_info_flag.out b/tests/022_info_flag.out index 9421387a69..163746f112 100644 --- a/tests/022_info_flag.out +++ b/tests/022_info_flag.out @@ -2,3 +2,5 @@ local: [WILDCARD]deps/http/127.0.0.1_PORT4545/tests/003_relative_import.ts type: TypeScript compiled: [WILDCARD].js map: [WILDCARD].js.map +deps: http://127.0.0.1:4545/tests/003_relative_import.ts +| http://127.0.0.1:4545/tests/subdir/print_hello.ts