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:
David Sherret 2023-04-13 14:03:07 -04:00 committed by GitHub
parent 6e8618ae0f
commit d192d84a0e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 102 additions and 80 deletions

View file

@ -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()
}
}