diff options
Diffstat (limited to 'cli/emit.rs')
-rw-r--r-- | cli/emit.rs | 177 |
1 files changed, 135 insertions, 42 deletions
diff --git a/cli/emit.rs b/cli/emit.rs index 923bb4ea0..a3352e01f 100644 --- a/cli/emit.rs +++ b/cli/emit.rs @@ -17,8 +17,8 @@ use std::sync::Arc; pub struct Emitter { emit_cache: EmitCache, parsed_source_cache: Arc<ParsedSourceCache>, - transpile_options: deno_ast::TranspileOptions, - emit_options: deno_ast::EmitOptions, + transpile_and_emit_options: + Arc<(deno_ast::TranspileOptions, deno_ast::EmitOptions)>, // cached hash of the transpile and emit options transpile_and_emit_options_hash: u64, } @@ -39,16 +39,16 @@ impl Emitter { Self { emit_cache, parsed_source_cache, - emit_options, - transpile_options, + transpile_and_emit_options: Arc::new((transpile_options, emit_options)), transpile_and_emit_options_hash, } } - pub fn cache_module_emits( + pub async fn cache_module_emits( &self, graph: &ModuleGraph, ) -> Result<(), AnyError> { + // todo(dsherret): we could do this concurrently for module in graph.modules() { if let Module::Js(module) = module { let is_emittable = matches!( @@ -60,11 +60,13 @@ impl Emitter { | MediaType::Tsx ); if is_emittable { - self.emit_parsed_source( - &module.specifier, - module.media_type, - &module.source, - )?; + self + .emit_parsed_source( + &module.specifier, + module.media_type, + &module.source, + ) + .await?; } } } @@ -81,42 +83,70 @@ impl Emitter { self.emit_cache.get_emit_code(specifier, source_hash) } - pub fn emit_parsed_source( + pub async fn emit_parsed_source( &self, specifier: &ModuleSpecifier, media_type: MediaType, source: &Arc<str>, ) -> Result<ModuleCodeString, AnyError> { - let source_hash = self.get_source_hash(source); + // Note: keep this in sync with the sync version below + let helper = EmitParsedSourceHelper(self); + match helper.pre_emit_parsed_source(specifier, source) { + PreEmitResult::Cached(emitted_text) => Ok(emitted_text), + PreEmitResult::NotCached { source_hash } => { + let parsed_source_cache = self.parsed_source_cache.clone(); + let transpile_and_emit_options = + self.transpile_and_emit_options.clone(); + let transpile_result = deno_core::unsync::spawn_blocking({ + let specifier = specifier.clone(); + let source = source.clone(); + move || -> Result<_, AnyError> { + EmitParsedSourceHelper::transpile( + &parsed_source_cache, + &specifier, + source.clone(), + media_type, + &transpile_and_emit_options.0, + &transpile_and_emit_options.1, + ) + } + }) + .await + .unwrap()?; + Ok(helper.post_emit_parsed_source( + specifier, + transpile_result, + source_hash, + )) + } + } + } - if let Some(emit_code) = - self.emit_cache.get_emit_code(specifier, source_hash) - { - Ok(emit_code.into()) - } else { - // nothing else needs the parsed source at this point, so remove from - // the cache in order to not transpile owned - let parsed_source = self.parsed_source_cache.remove_or_parse_module( - specifier, - source.clone(), - media_type, - )?; - let transpiled_source = match parsed_source - .transpile(&self.transpile_options, &self.emit_options)? - { - TranspileResult::Owned(source) => source, - TranspileResult::Cloned(source) => { - debug_assert!(false, "Transpile owned failed."); - source - } - }; - 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()) + pub fn emit_parsed_source_sync( + &self, + specifier: &ModuleSpecifier, + media_type: MediaType, + source: &Arc<str>, + ) -> Result<ModuleCodeString, AnyError> { + // Note: keep this in sync with the async version above + let helper = EmitParsedSourceHelper(self); + match helper.pre_emit_parsed_source(specifier, source) { + PreEmitResult::Cached(emitted_text) => Ok(emitted_text), + PreEmitResult::NotCached { source_hash } => { + let transpile_result = EmitParsedSourceHelper::transpile( + &self.parsed_source_cache, + specifier, + source.clone(), + media_type, + &self.transpile_and_emit_options.0, + &self.transpile_and_emit_options.1, + )?; + Ok(helper.post_emit_parsed_source( + specifier, + transpile_result, + source_hash, + )) + } } } @@ -134,10 +164,10 @@ impl Emitter { let parsed_source = self .parsed_source_cache .remove_or_parse_module(specifier, source_arc, media_type)?; - let mut options = self.emit_options.clone(); + let mut options = self.transpile_and_emit_options.1.clone(); options.source_map = SourceMapOption::None; let transpiled_source = parsed_source - .transpile(&self.transpile_options, &options)? + .transpile(&self.transpile_and_emit_options.0, &options)? .into_source(); Ok(transpiled_source.text) } @@ -152,3 +182,66 @@ impl Emitter { .finish() } } + +enum PreEmitResult { + Cached(ModuleCodeString), + NotCached { source_hash: u64 }, +} + +/// Helper to share code between async and sync emit_parsed_source methods. +struct EmitParsedSourceHelper<'a>(&'a Emitter); + +impl<'a> EmitParsedSourceHelper<'a> { + pub fn pre_emit_parsed_source( + &self, + specifier: &ModuleSpecifier, + source: &Arc<str>, + ) -> PreEmitResult { + let source_hash = self.0.get_source_hash(source); + + if let Some(emit_code) = + self.0.emit_cache.get_emit_code(specifier, source_hash) + { + PreEmitResult::Cached(emit_code.into()) + } else { + PreEmitResult::NotCached { source_hash } + } + } + + pub fn transpile( + parsed_source_cache: &ParsedSourceCache, + specifier: &ModuleSpecifier, + source: Arc<str>, + media_type: MediaType, + transpile_options: &deno_ast::TranspileOptions, + emit_options: &deno_ast::EmitOptions, + ) -> Result<TranspileResult, AnyError> { + // nothing else needs the parsed source at this point, so remove from + // the cache in order to not transpile owned + let parsed_source = parsed_source_cache + .remove_or_parse_module(specifier, source, media_type)?; + Ok(parsed_source.transpile(transpile_options, emit_options)?) + } + + pub fn post_emit_parsed_source( + &self, + specifier: &ModuleSpecifier, + transpile_result: TranspileResult, + source_hash: u64, + ) -> ModuleCodeString { + let transpiled_source = match transpile_result { + TranspileResult::Owned(source) => source, + TranspileResult::Cloned(source) => { + debug_assert!(false, "Transpile owned failed."); + source + } + }; + debug_assert!(transpiled_source.source_map.is_none()); + self.0.emit_cache.set_emit_code( + specifier, + source_hash, + &transpiled_source.text, + ); + transpiled_source.text.into() + } +} |