diff --git a/cli/emit.rs b/cli/emit.rs index f69f70cc73..92c2409502 100644 --- a/cli/emit.rs +++ b/cli/emit.rs @@ -8,41 +8,99 @@ use deno_core::error::AnyError; use deno_core::ModuleCode; use deno_core::ModuleSpecifier; use deno_graph::MediaType; +use deno_graph::Module; +use deno_graph::ModuleGraph; use std::sync::Arc; -/// A hashing function that takes the source code and emit options -/// hash then generates a string hash which can be stored to -/// determine if the cached emit is valid or not. -pub fn get_source_hash(source_text: &str, emit_options_hash: u64) -> u64 { - FastInsecureHasher::new() - .write_str(source_text) - .write_u64(emit_options_hash) - .finish() +#[derive(Clone)] +pub struct Emitter { + emit_cache: EmitCache, + parsed_source_cache: ParsedSourceCache, + emit_options: deno_ast::EmitOptions, + // cached hash of the emit options + emit_options_hash: u64, } -pub fn emit_parsed_source( - emit_cache: &EmitCache, - parsed_source_cache: &ParsedSourceCache, - specifier: &ModuleSpecifier, - media_type: MediaType, - source: &Arc, - emit_options: &deno_ast::EmitOptions, - emit_config_hash: u64, -) -> Result { - let source_hash = get_source_hash(source, emit_config_hash); +impl Emitter { + pub fn new( + emit_cache: EmitCache, + parsed_source_cache: ParsedSourceCache, + emit_options: deno_ast::EmitOptions, + ) -> Self { + let emit_options_hash = FastInsecureHasher::new() + .write_hashable(&emit_options) + .finish(); + Self { + emit_cache, + parsed_source_cache, + emit_options, + emit_options_hash, + } + } - if let Some(emit_code) = emit_cache.get_emit_code(specifier, source_hash) { - Ok(emit_code.into()) - } else { - // this will use a cached version if it exists - let parsed_source = parsed_source_cache.get_or_parse_module( - specifier, - source.clone(), - media_type, - )?; - let transpiled_source = parsed_source.transpile(emit_options)?; - debug_assert!(transpiled_source.source_map.is_none()); - emit_cache.set_emit_code(specifier, source_hash, &transpiled_source.text); - Ok(transpiled_source.text.into()) + pub fn cache_module_emits( + &self, + graph: &ModuleGraph, + ) -> Result<(), AnyError> { + for module in graph.modules() { + if let Module::Esm(module) = module { + let is_emittable = matches!( + module.media_type, + MediaType::TypeScript + | MediaType::Mts + | MediaType::Cts + | MediaType::Jsx + | MediaType::Tsx + ); + if is_emittable { + self.emit_parsed_source( + &module.specifier, + module.media_type, + &module.source, + )?; + } + } + } + Ok(()) + } + + pub fn emit_parsed_source( + &self, + specifier: &ModuleSpecifier, + media_type: MediaType, + source: &Arc, + ) -> Result { + let source_hash = self.get_source_hash(source); + + if let Some(emit_code) = + self.emit_cache.get_emit_code(specifier, source_hash) + { + Ok(emit_code.into()) + } else { + // this will use a cached version if it exists + let parsed_source = self.parsed_source_cache.get_or_parse_module( + specifier, + source.clone(), + media_type, + )?; + let transpiled_source = parsed_source.transpile(&self.emit_options)?; + debug_assert!(transpiled_source.source_map.is_none()); + self.emit_cache.set_emit_code( + specifier, + source_hash, + &transpiled_source.text, + ); + Ok(transpiled_source.text.into()) + } + } + + /// A hashing function that takes the source code and uses the global emit + /// options then generates a string hash which can be stored to + /// determine if the cached emit is valid or not. + pub fn get_source_hash(&self, source_text: &str) -> u64 { + FastInsecureHasher::new() + .write_str(source_text) + .write_u64(self.emit_options_hash) + .finish() } } diff --git a/cli/main.rs b/cli/main.rs index 849e0979ca..60eb9288fa 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -71,7 +71,7 @@ async fn run_subcommand(flags: Flags) -> Result { DenoSubcommand::Cache(cache_flags) => { let ps = ProcState::from_flags(flags).await?; ps.load_and_type_check_files(&cache_flags.files).await?; - ps.cache_module_emits()?; + ps.emitter.cache_module_emits(&ps.graph())?; Ok(0) } DenoSubcommand::Check(check_flags) => { diff --git a/cli/module_loader.rs b/cli/module_loader.rs index b7df15e31c..7467435254 100644 --- a/cli/module_loader.rs +++ b/cli/module_loader.rs @@ -1,7 +1,6 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. use crate::args::TsTypeLib; -use crate::emit::emit_parsed_source; use crate::node; use crate::proc_state::ProcState; use crate::util::text_encoding::code_without_source_map; @@ -117,14 +116,10 @@ impl CliModuleLoader { | MediaType::Jsx | MediaType::Tsx => { // get emit text - emit_parsed_source( - &self.ps.emit_cache, - &self.ps.parsed_source_cache, + self.ps.emitter.emit_parsed_source( specifier, *media_type, source, - &self.ps.emit_options, - self.ps.emit_options_hash, )? } MediaType::TsBuildInfo | MediaType::Wasm | MediaType::SourceMap => { diff --git a/cli/proc_state.rs b/cli/proc_state.rs index e9d5438021..3f6066370e 100644 --- a/cli/proc_state.rs +++ b/cli/proc_state.rs @@ -11,12 +11,11 @@ use crate::cache; use crate::cache::Caches; use crate::cache::DenoDir; use crate::cache::EmitCache; -use crate::cache::FastInsecureHasher; use crate::cache::HttpCache; use crate::cache::NodeAnalysisCache; use crate::cache::ParsedSourceCache; use crate::cache::TypeCheckCache; -use crate::emit::emit_parsed_source; +use crate::emit::Emitter; use crate::file_fetcher::FileFetcher; use crate::graph_util::build_graph_with_npm_resolution; use crate::graph_util::graph_lock_or_exit; @@ -36,7 +35,6 @@ use crate::tools::check; use crate::util::progress_bar::ProgressBar; use crate::util::progress_bar::ProgressBarStyle; -use deno_ast::MediaType; use deno_core::anyhow::anyhow; use deno_core::anyhow::Context; use deno_core::error::custom_error; @@ -80,8 +78,7 @@ pub struct Inner { pub http_client: HttpClient, pub options: Arc, pub emit_cache: EmitCache, - pub emit_options: deno_ast::EmitOptions, - pub emit_options_hash: u64, + pub emitter: Emitter, graph_container: ModuleGraphContainer, pub lockfile: Option>>, pub maybe_import_map: Option>, @@ -143,8 +140,7 @@ impl ProcState { caches: self.caches.clone(), options: self.options.clone(), emit_cache: self.emit_cache.clone(), - emit_options_hash: self.emit_options_hash, - emit_options: self.emit_options.clone(), + emitter: self.emitter.clone(), file_fetcher: self.file_fetcher.clone(), http_client: self.http_client.clone(), graph_container: Default::default(), @@ -301,6 +297,12 @@ impl ProcState { let emit_cache = EmitCache::new(dir.gen_cache.clone()); let parsed_source_cache = ParsedSourceCache::new(caches.dep_analysis_db(&dir)); + let emit_options: deno_ast::EmitOptions = ts_config_result.ts_config.into(); + let emitter = Emitter::new( + emit_cache.clone(), + parsed_source_cache.clone(), + emit_options, + ); let npm_cache = NpmCache::from_deno_dir( &dir, cli_options.cache_setting(), @@ -310,16 +312,12 @@ impl ProcState { let node_analysis_cache = NodeAnalysisCache::new(caches.node_analysis_db(&dir)); - let emit_options: deno_ast::EmitOptions = ts_config_result.ts_config.into(); Ok(ProcState(Arc::new(Inner { dir, caches, options: cli_options, emit_cache, - emit_options_hash: FastInsecureHasher::new() - .write_hashable(&emit_options) - .finish(), - emit_options, + emitter, file_fetcher: Arc::new(file_fetcher), http_client, graph_container: Default::default(), @@ -626,34 +624,6 @@ impl ProcState { resolution } - pub fn cache_module_emits(&self) -> Result<(), AnyError> { - let graph = self.graph(); - for module in graph.modules() { - if let Module::Esm(module) = module { - let is_emittable = matches!( - module.media_type, - MediaType::TypeScript - | MediaType::Mts - | MediaType::Cts - | MediaType::Jsx - | MediaType::Tsx - ); - if is_emittable { - emit_parsed_source( - &self.emit_cache, - &self.parsed_source_cache, - &module.specifier, - module.media_type, - &module.source, - &self.emit_options, - self.emit_options_hash, - )?; - } - } - } - Ok(()) - } - /// Creates the default loader used for creating a graph. pub fn create_graph_loader(&self) -> cache::FetchCacher { cache::FetchCacher::new( diff --git a/cli/tools/coverage/mod.rs b/cli/tools/coverage/mod.rs index 87c9836006..75ee833b0a 100644 --- a/cli/tools/coverage/mod.rs +++ b/cli/tools/coverage/mod.rs @@ -4,7 +4,6 @@ use crate::args::CoverageFlags; use crate::args::FileFlags; use crate::args::Flags; use crate::colors; -use crate::emit::get_source_hash; use crate::proc_state::ProcState; use crate::tools::fmt::format_json; use crate::util::fs::FileCollector; @@ -698,7 +697,7 @@ pub async fn cover_files( | MediaType::Mts | MediaType::Cts | MediaType::Tsx => { - let source_hash = get_source_hash(&file.source, ps.emit_options_hash); + let source_hash = ps.emitter.get_source_hash(&file.source); match ps.emit_cache.get_emit_code(&file.specifier, source_hash) { Some(code) => code.into(), None => {