mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 09:31:22 -05:00
refactor(cli): add Emitter
struct (#18690)
Removes the functions in the `emit` module and replaces them with an `Emitter` struct that can have "ctor dependencies" injected rather than using functions to pass along the dependencies. This is part of a long term refactor to move more functionality out of proc state.
This commit is contained in:
parent
6e8618ae0f
commit
d192d84a0e
5 changed files with 102 additions and 80 deletions
120
cli/emit.rs
120
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<str>,
|
||||
emit_options: &deno_ast::EmitOptions,
|
||||
emit_config_hash: u64,
|
||||
) -> Result<ModuleCode, AnyError> {
|
||||
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<str>,
|
||||
) -> Result<ModuleCode, AnyError> {
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ async fn run_subcommand(flags: Flags) -> Result<i32, AnyError> {
|
|||
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) => {
|
||||
|
|
|
@ -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 => {
|
||||
|
|
|
@ -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<CliOptions>,
|
||||
pub emit_cache: EmitCache,
|
||||
pub emit_options: deno_ast::EmitOptions,
|
||||
pub emit_options_hash: u64,
|
||||
pub emitter: Emitter,
|
||||
graph_container: ModuleGraphContainer,
|
||||
pub lockfile: Option<Arc<Mutex<Lockfile>>>,
|
||||
pub maybe_import_map: Option<Arc<ImportMap>>,
|
||||
|
@ -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(
|
||||
|
|
|
@ -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 => {
|
||||
|
|
Loading…
Add table
Reference in a new issue