mirror of
https://github.com/denoland/deno.git
synced 2024-12-21 23:04:45 -05:00
perf: do not clone swc Program
when transpiling (#23365)
This commit is contained in:
parent
76df7d7c9b
commit
e277490c82
3 changed files with 68 additions and 39 deletions
55
cli/cache/parsed_source.rs
vendored
55
cli/cache/parsed_source.rs
vendored
|
@ -8,8 +8,10 @@ use deno_ast::ModuleSpecifier;
|
|||
use deno_ast::ParsedSource;
|
||||
use deno_core::parking_lot::Mutex;
|
||||
use deno_graph::CapturingModuleParser;
|
||||
use deno_graph::DefaultModuleParser;
|
||||
use deno_graph::ModuleParser;
|
||||
use deno_graph::ParseOptions;
|
||||
use deno_graph::ParsedSourceStore;
|
||||
|
||||
/// Lazily parses JS/TS sources from a `deno_graph::ModuleGraph` given
|
||||
/// a `ParsedSourceCache`. Note that deno_graph doesn't necessarily cause
|
||||
|
@ -54,30 +56,38 @@ impl ParsedSourceCache {
|
|||
&self,
|
||||
module: &deno_graph::JsModule,
|
||||
) -> Result<ParsedSource, deno_ast::ParseDiagnostic> {
|
||||
self.get_or_parse_module(
|
||||
&module.specifier,
|
||||
module.source.clone(),
|
||||
module.media_type,
|
||||
)
|
||||
}
|
||||
|
||||
/// Gets the matching `ParsedSource` from the cache
|
||||
/// or parses a new one and stores that in the cache.
|
||||
pub fn get_or_parse_module(
|
||||
&self,
|
||||
specifier: &deno_graph::ModuleSpecifier,
|
||||
source: Arc<str>,
|
||||
media_type: MediaType,
|
||||
) -> deno_core::anyhow::Result<ParsedSource, deno_ast::ParseDiagnostic> {
|
||||
let parser = self.as_capturing_parser();
|
||||
// this will conditionally parse because it's using a CapturingModuleParser
|
||||
parser.parse_module(ParseOptions {
|
||||
specifier: &module.specifier,
|
||||
source: module.source.clone(),
|
||||
media_type: module.media_type,
|
||||
// don't bother enabling because this method is currently only used for vendoring
|
||||
scope_analysis: false,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn remove_or_parse_module(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
source: Arc<str>,
|
||||
media_type: MediaType,
|
||||
) -> Result<ParsedSource, deno_ast::ParseDiagnostic> {
|
||||
if let Some(parsed_source) = self.remove_parsed_source(specifier) {
|
||||
if parsed_source.media_type() == media_type
|
||||
&& parsed_source.text_info().text_str() == source.as_ref()
|
||||
{
|
||||
return Ok(parsed_source);
|
||||
}
|
||||
}
|
||||
let options = ParseOptions {
|
||||
specifier,
|
||||
source,
|
||||
media_type,
|
||||
// don't bother enabling because this method is currently only used for emitting
|
||||
scope_analysis: false,
|
||||
})
|
||||
};
|
||||
DefaultModuleParser.parse_module(options)
|
||||
}
|
||||
|
||||
/// Frees the parsed source from memory.
|
||||
|
@ -100,7 +110,7 @@ impl ParsedSourceCache {
|
|||
impl deno_graph::ParsedSourceStore for ParsedSourceCache {
|
||||
fn set_parsed_source(
|
||||
&self,
|
||||
specifier: deno_graph::ModuleSpecifier,
|
||||
specifier: ModuleSpecifier,
|
||||
parsed_source: ParsedSource,
|
||||
) -> Option<ParsedSource> {
|
||||
self.sources.lock().insert(specifier, parsed_source)
|
||||
|
@ -108,14 +118,21 @@ impl deno_graph::ParsedSourceStore for ParsedSourceCache {
|
|||
|
||||
fn get_parsed_source(
|
||||
&self,
|
||||
specifier: &deno_graph::ModuleSpecifier,
|
||||
specifier: &ModuleSpecifier,
|
||||
) -> Option<ParsedSource> {
|
||||
self.sources.lock().get(specifier).cloned()
|
||||
}
|
||||
|
||||
fn remove_parsed_source(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
) -> Option<ParsedSource> {
|
||||
self.sources.lock().remove(specifier)
|
||||
}
|
||||
|
||||
fn get_scope_analysis_parsed_source(
|
||||
&self,
|
||||
specifier: &deno_graph::ModuleSpecifier,
|
||||
specifier: &ModuleSpecifier,
|
||||
) -> Option<ParsedSource> {
|
||||
let mut sources = self.sources.lock();
|
||||
let parsed_source = sources.get(specifier)?;
|
||||
|
|
24
cli/emit.rs
24
cli/emit.rs
|
@ -93,14 +93,24 @@ impl Emitter {
|
|||
{
|
||||
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(
|
||||
// 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 =
|
||||
parsed_source.transpile(&self.transpile_options, &self.emit_options)?;
|
||||
let transpiled_source = match parsed_source
|
||||
.transpile_owned(&self.transpile_options, &self.emit_options)
|
||||
{
|
||||
Ok(result) => result?,
|
||||
Err(parsed_source) => {
|
||||
// transpile_owned is more efficient and should be preferred
|
||||
debug_assert!(false, "Transpile owned failed.");
|
||||
parsed_source
|
||||
.transpile(&self.transpile_options, &self.emit_options)?
|
||||
}
|
||||
};
|
||||
debug_assert!(transpiled_source.source_map.is_none());
|
||||
self.emit_cache.set_emit_code(
|
||||
specifier,
|
||||
|
@ -124,11 +134,11 @@ impl Emitter {
|
|||
let source_arc: Arc<str> = source_code.into();
|
||||
let parsed_source = self
|
||||
.parsed_source_cache
|
||||
.get_or_parse_module(specifier, source_arc, media_type)?;
|
||||
.remove_or_parse_module(specifier, source_arc, media_type)?;
|
||||
let mut options = self.emit_options;
|
||||
options.source_map = SourceMapOption::None;
|
||||
let transpiled_source =
|
||||
parsed_source.transpile(&self.transpile_options, &options)?;
|
||||
let transpiled_source = parsed_source
|
||||
.transpile_owned_with_fallback(&self.transpile_options, &options)?;
|
||||
Ok(transpiled_source.text)
|
||||
}
|
||||
|
||||
|
|
|
@ -95,20 +95,22 @@ pub fn maybe_transpile_source(
|
|||
scope_analysis: false,
|
||||
maybe_syntax: None,
|
||||
})?;
|
||||
let transpiled_source = parsed.transpile(
|
||||
&deno_ast::TranspileOptions {
|
||||
imports_not_used_as_values: deno_ast::ImportsNotUsedAsValues::Remove,
|
||||
..Default::default()
|
||||
},
|
||||
&deno_ast::EmitOptions {
|
||||
source_map: if cfg!(debug_assertions) {
|
||||
SourceMapOption::Separate
|
||||
} else {
|
||||
SourceMapOption::None
|
||||
let transpiled_source = parsed
|
||||
.transpile_owned(
|
||||
&deno_ast::TranspileOptions {
|
||||
imports_not_used_as_values: deno_ast::ImportsNotUsedAsValues::Remove,
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
&deno_ast::EmitOptions {
|
||||
source_map: if cfg!(debug_assertions) {
|
||||
SourceMapOption::Separate
|
||||
} else {
|
||||
SourceMapOption::None
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.unwrap()?;
|
||||
|
||||
let maybe_source_map: Option<SourceMapData> = transpiled_source
|
||||
.source_map
|
||||
|
|
Loading…
Reference in a new issue