summaryrefslogtreecommitdiff
path: root/cli/emit.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/emit.rs')
-rw-r--r--cli/emit.rs177
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()
+ }
+}