refactor(ext/node): CjsCodeAnalyzer - analyze_cjs optionally pass source text (#19896)

This commit is contained in:
David Sherret 2023-07-24 15:35:13 -04:00 committed by GitHub
parent d7a9ed9714
commit 40008c73bb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 43 additions and 29 deletions

View file

@ -475,7 +475,8 @@ impl CliFactory {
let caches = self.caches()?;
let node_analysis_cache =
NodeAnalysisCache::new(caches.node_analysis_db());
let cjs_esm_analyzer = CliCjsCodeAnalyzer::new(node_analysis_cache);
let cjs_esm_analyzer =
CliCjsCodeAnalyzer::new(node_analysis_cache, self.fs().clone());
Ok(Arc::new(NodeCodeTranslator::new(
cjs_esm_analyzer,

View file

@ -1,9 +1,12 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use std::borrow::Cow;
use deno_ast::CjsAnalysis;
use deno_ast::MediaType;
use deno_ast::ModuleSpecifier;
use deno_core::error::AnyError;
use deno_runtime::deno_fs;
use deno_runtime::deno_node::analyze::CjsAnalysis as ExtNodeCjsAnalysis;
use deno_runtime::deno_node::analyze::CjsCodeAnalyzer;
use deno_runtime::deno_node::analyze::NodeCodeTranslator;
@ -34,11 +37,12 @@ pub fn resolve_specifier_into_node_modules(
pub struct CliCjsCodeAnalyzer {
cache: NodeAnalysisCache,
fs: deno_fs::FileSystemRc,
}
impl CliCjsCodeAnalyzer {
pub fn new(cache: NodeAnalysisCache) -> Self {
Self { cache }
pub fn new(cache: NodeAnalysisCache, fs: deno_fs::FileSystemRc) -> Self {
Self { cache, fs }
}
fn inner_cjs_analysis(
@ -83,9 +87,15 @@ impl CjsCodeAnalyzer for CliCjsCodeAnalyzer {
fn analyze_cjs(
&self,
specifier: &ModuleSpecifier,
source: &str,
source: Option<&str>,
) -> Result<ExtNodeCjsAnalysis, AnyError> {
let analysis = self.inner_cjs_analysis(specifier, source)?;
let source = match source {
Some(source) => Cow::Borrowed(source),
None => {
Cow::Owned(self.fs.read_to_string(&specifier.to_file_path().unwrap())?)
}
};
let analysis = self.inner_cjs_analysis(specifier, &source)?;
Ok(ExtNodeCjsAnalysis {
exports: analysis.exports,
reexports: analysis.reexports,

View file

@ -366,7 +366,8 @@ pub async fn run(
let cjs_resolutions = Arc::new(CjsResolutionStore::default());
let cache_db = Caches::new(deno_dir_provider.clone());
let node_analysis_cache = NodeAnalysisCache::new(cache_db.node_analysis_db());
let cjs_esm_code_analyzer = CliCjsCodeAnalyzer::new(node_analysis_cache);
let cjs_esm_code_analyzer =
CliCjsCodeAnalyzer::new(node_analysis_cache, fs.clone());
let node_code_translator = Arc::new(NodeCodeTranslator::new(
cjs_esm_code_analyzer,
fs.clone(),

View file

@ -29,10 +29,15 @@ pub struct CjsAnalysis {
pub trait CjsCodeAnalyzer {
/// Analyzes CommonJs code for exports and reexports, which is
/// then used to determine the wrapper ESM module exports.
///
/// Note that the source is provided by the caller when the caller
/// already has it. If the source is needed by the implementation,
/// then it can use the provided source, or otherwise load it if
/// necessary.
fn analyze_cjs(
&self,
specifier: &ModuleSpecifier,
source: &str,
maybe_source: Option<&str>,
) -> Result<CjsAnalysis, AnyError>;
}
@ -73,7 +78,9 @@ impl<TCjsCodeAnalyzer: CjsCodeAnalyzer> NodeCodeTranslator<TCjsCodeAnalyzer> {
let mut temp_var_count = 0;
let mut handled_reexports: HashSet<String> = HashSet::default();
let analysis = self.cjs_code_analyzer.analyze_cjs(specifier, source)?;
let analysis = self
.cjs_code_analyzer
.analyze_cjs(specifier, Some(source))?;
let mut source = vec![
r#"import {createRequire as __internalCreateRequire} from "node:module";
@ -100,7 +107,7 @@ impl<TCjsCodeAnalyzer: CjsCodeAnalyzer> NodeCodeTranslator<TCjsCodeAnalyzer> {
handled_reexports.insert(reexport.to_string());
// First, resolve relate reexport specifier
// First, resolve the reexport specifier
let resolved_reexport = self.resolve(
&reexport,
&referrer,
@ -110,35 +117,30 @@ impl<TCjsCodeAnalyzer: CjsCodeAnalyzer> NodeCodeTranslator<TCjsCodeAnalyzer> {
NodeResolutionMode::Execution,
permissions,
)?;
// Second, read the source code from disk
// Second, resolve its exports and re-exports
let reexport_specifier =
ModuleSpecifier::from_file_path(&resolved_reexport).unwrap();
let reexport_file_text = self
.fs
.read_to_string(&resolved_reexport)
.map_err(AnyError::from)
let analysis = self
.cjs_code_analyzer
.analyze_cjs(&reexport_specifier, None)
.with_context(|| {
format!(
"Could not find '{}' ({}) referenced from {}",
"Could not load '{}' ({}) referenced from {}",
reexport, reexport_specifier, referrer
)
})?;
{
let analysis = self
.cjs_code_analyzer
.analyze_cjs(&reexport_specifier, &reexport_file_text)?;
for reexport in analysis.reexports {
reexports_to_handle.push_back((reexport, reexport_specifier.clone()));
}
all_exports.extend(
analysis
.exports
.into_iter()
.filter(|e| e.as_str() != "default"),
);
for reexport in analysis.reexports {
reexports_to_handle.push_back((reexport, reexport_specifier.clone()));
}
all_exports.extend(
analysis
.exports
.into_iter()
.filter(|e| e.as_str() != "default"),
);
}
source.push(format!(