mirror of
https://github.com/denoland/deno.git
synced 2025-01-11 08:33:43 -05:00
refactor(cli): decouple resolvers from module_loader.rs
for standalone use (#22147)
It makes it easier to write a standalone bin target for `deno compile` without pulling a lot of the tooling and tsc loader logic
This commit is contained in:
parent
d9191db0ce
commit
ed65bc6abc
4 changed files with 244 additions and 242 deletions
|
@ -23,11 +23,8 @@ use crate::graph_util::FileWatcherReporter;
|
||||||
use crate::graph_util::ModuleGraphBuilder;
|
use crate::graph_util::ModuleGraphBuilder;
|
||||||
use crate::graph_util::ModuleGraphContainer;
|
use crate::graph_util::ModuleGraphContainer;
|
||||||
use crate::http_util::HttpClient;
|
use crate::http_util::HttpClient;
|
||||||
use crate::module_loader::CjsResolutionStore;
|
|
||||||
use crate::module_loader::CliModuleLoaderFactory;
|
use crate::module_loader::CliModuleLoaderFactory;
|
||||||
use crate::module_loader::CliNodeResolver;
|
|
||||||
use crate::module_loader::ModuleLoadPreparer;
|
use crate::module_loader::ModuleLoadPreparer;
|
||||||
use crate::module_loader::NpmModuleLoader;
|
|
||||||
use crate::node::CliCjsCodeAnalyzer;
|
use crate::node::CliCjsCodeAnalyzer;
|
||||||
use crate::node::CliNodeCodeTranslator;
|
use crate::node::CliNodeCodeTranslator;
|
||||||
use crate::npm::create_cli_npm_resolver;
|
use crate::npm::create_cli_npm_resolver;
|
||||||
|
@ -37,8 +34,11 @@ use crate::npm::CliNpmResolverCreateOptions;
|
||||||
use crate::npm::CliNpmResolverManagedCreateOptions;
|
use crate::npm::CliNpmResolverManagedCreateOptions;
|
||||||
use crate::npm::CliNpmResolverManagedPackageJsonInstallerOption;
|
use crate::npm::CliNpmResolverManagedPackageJsonInstallerOption;
|
||||||
use crate::npm::CliNpmResolverManagedSnapshotOption;
|
use crate::npm::CliNpmResolverManagedSnapshotOption;
|
||||||
|
use crate::resolver::CjsResolutionStore;
|
||||||
use crate::resolver::CliGraphResolver;
|
use crate::resolver::CliGraphResolver;
|
||||||
use crate::resolver::CliGraphResolverOptions;
|
use crate::resolver::CliGraphResolverOptions;
|
||||||
|
use crate::resolver::CliNodeResolver;
|
||||||
|
use crate::resolver::NpmModuleLoader;
|
||||||
use crate::resolver::SloppyImportsResolver;
|
use crate::resolver::SloppyImportsResolver;
|
||||||
use crate::standalone::DenoCompileBinaryWriter;
|
use crate::standalone::DenoCompileBinaryWriter;
|
||||||
use crate::tools::check::TypeChecker;
|
use crate::tools::check::TypeChecker;
|
||||||
|
|
|
@ -14,9 +14,10 @@ use crate::graph_util::FileWatcherReporter;
|
||||||
use crate::graph_util::ModuleGraphBuilder;
|
use crate::graph_util::ModuleGraphBuilder;
|
||||||
use crate::graph_util::ModuleGraphContainer;
|
use crate::graph_util::ModuleGraphContainer;
|
||||||
use crate::node;
|
use crate::node;
|
||||||
use crate::node::CliNodeCodeTranslator;
|
|
||||||
use crate::npm::CliNpmResolver;
|
|
||||||
use crate::resolver::CliGraphResolver;
|
use crate::resolver::CliGraphResolver;
|
||||||
|
use crate::resolver::CliNodeResolver;
|
||||||
|
use crate::resolver::ModuleCodeStringSource;
|
||||||
|
use crate::resolver::NpmModuleLoader;
|
||||||
use crate::tools::check;
|
use crate::tools::check;
|
||||||
use crate::tools::check::TypeChecker;
|
use crate::tools::check::TypeChecker;
|
||||||
use crate::util::progress_bar::ProgressBar;
|
use crate::util::progress_bar::ProgressBar;
|
||||||
|
@ -53,14 +54,10 @@ use deno_graph::Resolution;
|
||||||
use deno_lockfile::Lockfile;
|
use deno_lockfile::Lockfile;
|
||||||
use deno_runtime::colors;
|
use deno_runtime::colors;
|
||||||
use deno_runtime::deno_fs;
|
use deno_runtime::deno_fs;
|
||||||
use deno_runtime::deno_node::NodeResolution;
|
|
||||||
use deno_runtime::deno_node::NodeResolutionMode;
|
|
||||||
use deno_runtime::deno_node::NodeResolver;
|
|
||||||
use deno_runtime::permissions::PermissionsContainer;
|
use deno_runtime::permissions::PermissionsContainer;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::path::Path;
|
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
@ -271,12 +268,6 @@ impl ModuleLoadPreparer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ModuleCodeStringSource {
|
|
||||||
pub code: ModuleCodeString,
|
|
||||||
pub found_url: ModuleSpecifier,
|
|
||||||
pub media_type: MediaType,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct PreparedModuleLoader {
|
struct PreparedModuleLoader {
|
||||||
emitter: Arc<Emitter>,
|
emitter: Arc<Emitter>,
|
||||||
graph_container: Arc<ModuleGraphContainer>,
|
graph_container: Arc<ModuleGraphContainer>,
|
||||||
|
@ -741,226 +732,3 @@ impl SourceMapGetter for CliSourceMapGetter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CliNodeResolver {
|
|
||||||
cjs_resolutions: Arc<CjsResolutionStore>,
|
|
||||||
node_resolver: Arc<NodeResolver>,
|
|
||||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CliNodeResolver {
|
|
||||||
pub fn new(
|
|
||||||
cjs_resolutions: Arc<CjsResolutionStore>,
|
|
||||||
node_resolver: Arc<NodeResolver>,
|
|
||||||
npm_resolver: Arc<dyn CliNpmResolver>,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
cjs_resolutions,
|
|
||||||
node_resolver,
|
|
||||||
npm_resolver,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn in_npm_package(&self, referrer: &ModuleSpecifier) -> bool {
|
|
||||||
self.npm_resolver.in_npm_package(referrer)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve_if_in_npm_package(
|
|
||||||
&self,
|
|
||||||
specifier: &str,
|
|
||||||
referrer: &ModuleSpecifier,
|
|
||||||
permissions: &PermissionsContainer,
|
|
||||||
) -> Option<Result<ModuleSpecifier, AnyError>> {
|
|
||||||
if self.in_npm_package(referrer) {
|
|
||||||
// we're in an npm package, so use node resolution
|
|
||||||
Some(
|
|
||||||
self
|
|
||||||
.handle_node_resolve_result(self.node_resolver.resolve(
|
|
||||||
specifier,
|
|
||||||
referrer,
|
|
||||||
NodeResolutionMode::Execution,
|
|
||||||
permissions,
|
|
||||||
))
|
|
||||||
.with_context(|| {
|
|
||||||
format!("Could not resolve '{specifier}' from '{referrer}'.")
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve_req_reference(
|
|
||||||
&self,
|
|
||||||
req_ref: &NpmPackageReqReference,
|
|
||||||
permissions: &PermissionsContainer,
|
|
||||||
referrer: &ModuleSpecifier,
|
|
||||||
) -> Result<ModuleSpecifier, AnyError> {
|
|
||||||
let package_folder = self
|
|
||||||
.npm_resolver
|
|
||||||
.resolve_pkg_folder_from_deno_module_req(req_ref.req(), referrer)?;
|
|
||||||
self
|
|
||||||
.resolve_package_sub_path(
|
|
||||||
&package_folder,
|
|
||||||
req_ref.sub_path(),
|
|
||||||
referrer,
|
|
||||||
permissions,
|
|
||||||
)
|
|
||||||
.with_context(|| format!("Could not resolve '{}'.", req_ref))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve_package_sub_path(
|
|
||||||
&self,
|
|
||||||
package_folder: &Path,
|
|
||||||
sub_path: Option<&str>,
|
|
||||||
referrer: &ModuleSpecifier,
|
|
||||||
permissions: &PermissionsContainer,
|
|
||||||
) -> Result<ModuleSpecifier, AnyError> {
|
|
||||||
self.handle_node_resolve_result(
|
|
||||||
self.node_resolver.resolve_package_subpath_from_deno_module(
|
|
||||||
package_folder,
|
|
||||||
sub_path,
|
|
||||||
referrer,
|
|
||||||
NodeResolutionMode::Execution,
|
|
||||||
permissions,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_node_resolve_result(
|
|
||||||
&self,
|
|
||||||
result: Result<Option<NodeResolution>, AnyError>,
|
|
||||||
) -> Result<ModuleSpecifier, AnyError> {
|
|
||||||
let response = match result? {
|
|
||||||
Some(response) => response,
|
|
||||||
None => return Err(generic_error("not found")),
|
|
||||||
};
|
|
||||||
if let NodeResolution::CommonJs(specifier) = &response {
|
|
||||||
// remember that this was a common js resolution
|
|
||||||
self.cjs_resolutions.insert(specifier.clone());
|
|
||||||
}
|
|
||||||
Ok(response.into_url())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct NpmModuleLoader {
|
|
||||||
cjs_resolutions: Arc<CjsResolutionStore>,
|
|
||||||
node_code_translator: Arc<CliNodeCodeTranslator>,
|
|
||||||
fs: Arc<dyn deno_fs::FileSystem>,
|
|
||||||
node_resolver: Arc<CliNodeResolver>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NpmModuleLoader {
|
|
||||||
pub fn new(
|
|
||||||
cjs_resolutions: Arc<CjsResolutionStore>,
|
|
||||||
node_code_translator: Arc<CliNodeCodeTranslator>,
|
|
||||||
fs: Arc<dyn deno_fs::FileSystem>,
|
|
||||||
node_resolver: Arc<CliNodeResolver>,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
cjs_resolutions,
|
|
||||||
node_code_translator,
|
|
||||||
fs,
|
|
||||||
node_resolver,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn maybe_prepare_load(
|
|
||||||
&self,
|
|
||||||
specifier: &ModuleSpecifier,
|
|
||||||
) -> Option<Result<(), AnyError>> {
|
|
||||||
if self.node_resolver.in_npm_package(specifier) {
|
|
||||||
// nothing to prepare
|
|
||||||
Some(Ok(()))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn load_sync_if_in_npm_package(
|
|
||||||
&self,
|
|
||||||
specifier: &ModuleSpecifier,
|
|
||||||
maybe_referrer: Option<&ModuleSpecifier>,
|
|
||||||
permissions: &PermissionsContainer,
|
|
||||||
) -> Option<Result<ModuleCodeStringSource, AnyError>> {
|
|
||||||
if self.node_resolver.in_npm_package(specifier) {
|
|
||||||
Some(self.load_sync(specifier, maybe_referrer, permissions))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_sync(
|
|
||||||
&self,
|
|
||||||
specifier: &ModuleSpecifier,
|
|
||||||
maybe_referrer: Option<&ModuleSpecifier>,
|
|
||||||
permissions: &PermissionsContainer,
|
|
||||||
) -> Result<ModuleCodeStringSource, AnyError> {
|
|
||||||
let file_path = specifier.to_file_path().unwrap();
|
|
||||||
let code = self
|
|
||||||
.fs
|
|
||||||
.read_text_file_sync(&file_path)
|
|
||||||
.map_err(AnyError::from)
|
|
||||||
.with_context(|| {
|
|
||||||
if file_path.is_dir() {
|
|
||||||
// directory imports are not allowed when importing from an
|
|
||||||
// ES module, so provide the user with a helpful error message
|
|
||||||
let dir_path = file_path;
|
|
||||||
let mut msg = "Directory import ".to_string();
|
|
||||||
msg.push_str(&dir_path.to_string_lossy());
|
|
||||||
if let Some(referrer) = &maybe_referrer {
|
|
||||||
msg.push_str(" is not supported resolving import from ");
|
|
||||||
msg.push_str(referrer.as_str());
|
|
||||||
let entrypoint_name = ["index.mjs", "index.js", "index.cjs"]
|
|
||||||
.iter()
|
|
||||||
.find(|e| dir_path.join(e).is_file());
|
|
||||||
if let Some(entrypoint_name) = entrypoint_name {
|
|
||||||
msg.push_str("\nDid you mean to import ");
|
|
||||||
msg.push_str(entrypoint_name);
|
|
||||||
msg.push_str(" within the directory?");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
msg
|
|
||||||
} else {
|
|
||||||
let mut msg = "Unable to load ".to_string();
|
|
||||||
msg.push_str(&file_path.to_string_lossy());
|
|
||||||
if let Some(referrer) = &maybe_referrer {
|
|
||||||
msg.push_str(" imported from ");
|
|
||||||
msg.push_str(referrer.as_str());
|
|
||||||
}
|
|
||||||
msg
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let code = if self.cjs_resolutions.contains(specifier) {
|
|
||||||
// translate cjs to esm if it's cjs and inject node globals
|
|
||||||
self.node_code_translator.translate_cjs_to_esm(
|
|
||||||
specifier,
|
|
||||||
Some(code.as_str()),
|
|
||||||
permissions,
|
|
||||||
)?
|
|
||||||
} else {
|
|
||||||
// esm and json code is untouched
|
|
||||||
code
|
|
||||||
};
|
|
||||||
Ok(ModuleCodeStringSource {
|
|
||||||
code: code.into(),
|
|
||||||
found_url: specifier.clone(),
|
|
||||||
media_type: MediaType::from_specifier(specifier),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Keeps track of what module specifiers were resolved as CJS.
|
|
||||||
#[derive(Debug, Default)]
|
|
||||||
pub struct CjsResolutionStore(Mutex<HashSet<ModuleSpecifier>>);
|
|
||||||
|
|
||||||
impl CjsResolutionStore {
|
|
||||||
pub fn contains(&self, specifier: &ModuleSpecifier) -> bool {
|
|
||||||
self.0.lock().contains(specifier)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert(&self, specifier: ModuleSpecifier) {
|
|
||||||
self.0.lock().insert(specifier);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
236
cli/resolver.rs
236
cli/resolver.rs
|
@ -2,11 +2,14 @@
|
||||||
|
|
||||||
use deno_ast::MediaType;
|
use deno_ast::MediaType;
|
||||||
use deno_core::anyhow::anyhow;
|
use deno_core::anyhow::anyhow;
|
||||||
|
use deno_core::anyhow::Context;
|
||||||
|
use deno_core::error::generic_error;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::futures::future;
|
use deno_core::futures::future;
|
||||||
use deno_core::futures::future::LocalBoxFuture;
|
use deno_core::futures::future::LocalBoxFuture;
|
||||||
use deno_core::futures::FutureExt;
|
use deno_core::futures::FutureExt;
|
||||||
use deno_core::parking_lot::Mutex;
|
use deno_core::parking_lot::Mutex;
|
||||||
|
use deno_core::ModuleCodeString;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use deno_graph::source::NpmPackageReqResolution;
|
use deno_graph::source::NpmPackageReqResolution;
|
||||||
use deno_graph::source::NpmResolver;
|
use deno_graph::source::NpmResolver;
|
||||||
|
@ -15,6 +18,7 @@ use deno_graph::source::ResolveError;
|
||||||
use deno_graph::source::Resolver;
|
use deno_graph::source::Resolver;
|
||||||
use deno_graph::source::UnknownBuiltInNodeModuleError;
|
use deno_graph::source::UnknownBuiltInNodeModuleError;
|
||||||
use deno_graph::source::DEFAULT_JSX_IMPORT_SOURCE_MODULE;
|
use deno_graph::source::DEFAULT_JSX_IMPORT_SOURCE_MODULE;
|
||||||
|
use deno_runtime::deno_fs;
|
||||||
use deno_runtime::deno_fs::FileSystem;
|
use deno_runtime::deno_fs::FileSystem;
|
||||||
use deno_runtime::deno_node::is_builtin_node_module;
|
use deno_runtime::deno_node::is_builtin_node_module;
|
||||||
use deno_runtime::deno_node::parse_npm_pkg_name;
|
use deno_runtime::deno_node::parse_npm_pkg_name;
|
||||||
|
@ -28,6 +32,7 @@ use deno_semver::package::PackageReq;
|
||||||
use import_map::ImportMap;
|
use import_map::ImportMap;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -36,13 +41,242 @@ use crate::args::package_json::PackageJsonDeps;
|
||||||
use crate::args::JsxImportSourceConfig;
|
use crate::args::JsxImportSourceConfig;
|
||||||
use crate::args::PackageJsonDepsProvider;
|
use crate::args::PackageJsonDepsProvider;
|
||||||
use crate::graph_util::format_range_with_colors;
|
use crate::graph_util::format_range_with_colors;
|
||||||
use crate::module_loader::CjsResolutionStore;
|
use crate::node::CliNodeCodeTranslator;
|
||||||
use crate::npm::ByonmCliNpmResolver;
|
use crate::npm::ByonmCliNpmResolver;
|
||||||
use crate::npm::CliNpmResolver;
|
use crate::npm::CliNpmResolver;
|
||||||
use crate::npm::InnerCliNpmResolverRef;
|
use crate::npm::InnerCliNpmResolverRef;
|
||||||
use crate::util::path::specifier_to_file_path;
|
use crate::util::path::specifier_to_file_path;
|
||||||
use crate::util::sync::AtomicFlag;
|
use crate::util::sync::AtomicFlag;
|
||||||
|
|
||||||
|
pub struct ModuleCodeStringSource {
|
||||||
|
pub code: ModuleCodeString,
|
||||||
|
pub found_url: ModuleSpecifier,
|
||||||
|
pub media_type: MediaType,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CliNodeResolver {
|
||||||
|
cjs_resolutions: Arc<CjsResolutionStore>,
|
||||||
|
node_resolver: Arc<NodeResolver>,
|
||||||
|
pub(crate) npm_resolver: Arc<dyn CliNpmResolver>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CliNodeResolver {
|
||||||
|
pub fn new(
|
||||||
|
cjs_resolutions: Arc<CjsResolutionStore>,
|
||||||
|
node_resolver: Arc<NodeResolver>,
|
||||||
|
npm_resolver: Arc<dyn CliNpmResolver>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
cjs_resolutions,
|
||||||
|
node_resolver,
|
||||||
|
npm_resolver,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn in_npm_package(&self, referrer: &ModuleSpecifier) -> bool {
|
||||||
|
self.npm_resolver.in_npm_package(referrer)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resolve_if_in_npm_package(
|
||||||
|
&self,
|
||||||
|
specifier: &str,
|
||||||
|
referrer: &ModuleSpecifier,
|
||||||
|
permissions: &PermissionsContainer,
|
||||||
|
) -> Option<Result<ModuleSpecifier, AnyError>> {
|
||||||
|
if self.in_npm_package(referrer) {
|
||||||
|
// we're in an npm package, so use node resolution
|
||||||
|
Some(
|
||||||
|
self
|
||||||
|
.handle_node_resolve_result(self.node_resolver.resolve(
|
||||||
|
specifier,
|
||||||
|
referrer,
|
||||||
|
NodeResolutionMode::Execution,
|
||||||
|
permissions,
|
||||||
|
))
|
||||||
|
.with_context(|| {
|
||||||
|
format!("Could not resolve '{specifier}' from '{referrer}'.")
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resolve_req_reference(
|
||||||
|
&self,
|
||||||
|
req_ref: &NpmPackageReqReference,
|
||||||
|
permissions: &PermissionsContainer,
|
||||||
|
referrer: &ModuleSpecifier,
|
||||||
|
) -> Result<ModuleSpecifier, AnyError> {
|
||||||
|
let package_folder = self
|
||||||
|
.npm_resolver
|
||||||
|
.resolve_pkg_folder_from_deno_module_req(req_ref.req(), referrer)?;
|
||||||
|
self
|
||||||
|
.resolve_package_sub_path(
|
||||||
|
&package_folder,
|
||||||
|
req_ref.sub_path(),
|
||||||
|
referrer,
|
||||||
|
permissions,
|
||||||
|
)
|
||||||
|
.with_context(|| format!("Could not resolve '{}'.", req_ref))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resolve_package_sub_path(
|
||||||
|
&self,
|
||||||
|
package_folder: &Path,
|
||||||
|
sub_path: Option<&str>,
|
||||||
|
referrer: &ModuleSpecifier,
|
||||||
|
permissions: &PermissionsContainer,
|
||||||
|
) -> Result<ModuleSpecifier, AnyError> {
|
||||||
|
self.handle_node_resolve_result(
|
||||||
|
self.node_resolver.resolve_package_subpath_from_deno_module(
|
||||||
|
package_folder,
|
||||||
|
sub_path,
|
||||||
|
referrer,
|
||||||
|
NodeResolutionMode::Execution,
|
||||||
|
permissions,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_node_resolve_result(
|
||||||
|
&self,
|
||||||
|
result: Result<Option<NodeResolution>, AnyError>,
|
||||||
|
) -> Result<ModuleSpecifier, AnyError> {
|
||||||
|
let response = match result? {
|
||||||
|
Some(response) => response,
|
||||||
|
None => return Err(generic_error("not found")),
|
||||||
|
};
|
||||||
|
if let NodeResolution::CommonJs(specifier) = &response {
|
||||||
|
// remember that this was a common js resolution
|
||||||
|
self.cjs_resolutions.insert(specifier.clone());
|
||||||
|
}
|
||||||
|
Ok(response.into_url())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NpmModuleLoader {
|
||||||
|
cjs_resolutions: Arc<CjsResolutionStore>,
|
||||||
|
node_code_translator: Arc<CliNodeCodeTranslator>,
|
||||||
|
fs: Arc<dyn deno_fs::FileSystem>,
|
||||||
|
node_resolver: Arc<CliNodeResolver>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NpmModuleLoader {
|
||||||
|
pub fn new(
|
||||||
|
cjs_resolutions: Arc<CjsResolutionStore>,
|
||||||
|
node_code_translator: Arc<CliNodeCodeTranslator>,
|
||||||
|
fs: Arc<dyn deno_fs::FileSystem>,
|
||||||
|
node_resolver: Arc<CliNodeResolver>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
cjs_resolutions,
|
||||||
|
node_code_translator,
|
||||||
|
fs,
|
||||||
|
node_resolver,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn maybe_prepare_load(
|
||||||
|
&self,
|
||||||
|
specifier: &ModuleSpecifier,
|
||||||
|
) -> Option<Result<(), AnyError>> {
|
||||||
|
if self.node_resolver.in_npm_package(specifier) {
|
||||||
|
// nothing to prepare
|
||||||
|
Some(Ok(()))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_sync_if_in_npm_package(
|
||||||
|
&self,
|
||||||
|
specifier: &ModuleSpecifier,
|
||||||
|
maybe_referrer: Option<&ModuleSpecifier>,
|
||||||
|
permissions: &PermissionsContainer,
|
||||||
|
) -> Option<Result<ModuleCodeStringSource, AnyError>> {
|
||||||
|
if self.node_resolver.in_npm_package(specifier) {
|
||||||
|
Some(self.load_sync(specifier, maybe_referrer, permissions))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_sync(
|
||||||
|
&self,
|
||||||
|
specifier: &ModuleSpecifier,
|
||||||
|
maybe_referrer: Option<&ModuleSpecifier>,
|
||||||
|
permissions: &PermissionsContainer,
|
||||||
|
) -> Result<ModuleCodeStringSource, AnyError> {
|
||||||
|
let file_path = specifier.to_file_path().unwrap();
|
||||||
|
let code = self
|
||||||
|
.fs
|
||||||
|
.read_text_file_sync(&file_path)
|
||||||
|
.map_err(AnyError::from)
|
||||||
|
.with_context(|| {
|
||||||
|
if file_path.is_dir() {
|
||||||
|
// directory imports are not allowed when importing from an
|
||||||
|
// ES module, so provide the user with a helpful error message
|
||||||
|
let dir_path = file_path;
|
||||||
|
let mut msg = "Directory import ".to_string();
|
||||||
|
msg.push_str(&dir_path.to_string_lossy());
|
||||||
|
if let Some(referrer) = &maybe_referrer {
|
||||||
|
msg.push_str(" is not supported resolving import from ");
|
||||||
|
msg.push_str(referrer.as_str());
|
||||||
|
let entrypoint_name = ["index.mjs", "index.js", "index.cjs"]
|
||||||
|
.iter()
|
||||||
|
.find(|e| dir_path.join(e).is_file());
|
||||||
|
if let Some(entrypoint_name) = entrypoint_name {
|
||||||
|
msg.push_str("\nDid you mean to import ");
|
||||||
|
msg.push_str(entrypoint_name);
|
||||||
|
msg.push_str(" within the directory?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
msg
|
||||||
|
} else {
|
||||||
|
let mut msg = "Unable to load ".to_string();
|
||||||
|
msg.push_str(&file_path.to_string_lossy());
|
||||||
|
if let Some(referrer) = &maybe_referrer {
|
||||||
|
msg.push_str(" imported from ");
|
||||||
|
msg.push_str(referrer.as_str());
|
||||||
|
}
|
||||||
|
msg
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let code = if self.cjs_resolutions.contains(specifier) {
|
||||||
|
// translate cjs to esm if it's cjs and inject node globals
|
||||||
|
self.node_code_translator.translate_cjs_to_esm(
|
||||||
|
specifier,
|
||||||
|
Some(code.as_str()),
|
||||||
|
permissions,
|
||||||
|
)?
|
||||||
|
} else {
|
||||||
|
// esm and json code is untouched
|
||||||
|
code
|
||||||
|
};
|
||||||
|
Ok(ModuleCodeStringSource {
|
||||||
|
code: code.into(),
|
||||||
|
found_url: specifier.clone(),
|
||||||
|
media_type: MediaType::from_specifier(specifier),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Keeps track of what module specifiers were resolved as CJS.
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct CjsResolutionStore(Mutex<HashSet<ModuleSpecifier>>);
|
||||||
|
|
||||||
|
impl CjsResolutionStore {
|
||||||
|
pub fn contains(&self, specifier: &ModuleSpecifier) -> bool {
|
||||||
|
self.0.lock().contains(specifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert(&self, specifier: ModuleSpecifier) {
|
||||||
|
self.0.lock().insert(specifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Result of checking if a specifier is mapped via
|
/// Result of checking if a specifier is mapped via
|
||||||
/// an import map or package.json.
|
/// an import map or package.json.
|
||||||
pub enum MappedResolution {
|
pub enum MappedResolution {
|
||||||
|
|
|
@ -11,9 +11,6 @@ use crate::cache::DenoDirProvider;
|
||||||
use crate::cache::NodeAnalysisCache;
|
use crate::cache::NodeAnalysisCache;
|
||||||
use crate::file_fetcher::get_source_from_data_url;
|
use crate::file_fetcher::get_source_from_data_url;
|
||||||
use crate::http_util::HttpClient;
|
use crate::http_util::HttpClient;
|
||||||
use crate::module_loader::CjsResolutionStore;
|
|
||||||
use crate::module_loader::CliNodeResolver;
|
|
||||||
use crate::module_loader::NpmModuleLoader;
|
|
||||||
use crate::node::CliCjsCodeAnalyzer;
|
use crate::node::CliCjsCodeAnalyzer;
|
||||||
use crate::npm::create_cli_npm_resolver;
|
use crate::npm::create_cli_npm_resolver;
|
||||||
use crate::npm::CliNpmResolverByonmCreateOptions;
|
use crate::npm::CliNpmResolverByonmCreateOptions;
|
||||||
|
@ -22,7 +19,10 @@ use crate::npm::CliNpmResolverManagedCreateOptions;
|
||||||
use crate::npm::CliNpmResolverManagedPackageJsonInstallerOption;
|
use crate::npm::CliNpmResolverManagedPackageJsonInstallerOption;
|
||||||
use crate::npm::CliNpmResolverManagedSnapshotOption;
|
use crate::npm::CliNpmResolverManagedSnapshotOption;
|
||||||
use crate::npm::NpmCacheDir;
|
use crate::npm::NpmCacheDir;
|
||||||
|
use crate::resolver::CjsResolutionStore;
|
||||||
|
use crate::resolver::CliNodeResolver;
|
||||||
use crate::resolver::MappedSpecifierResolver;
|
use crate::resolver::MappedSpecifierResolver;
|
||||||
|
use crate::resolver::NpmModuleLoader;
|
||||||
use crate::util::progress_bar::ProgressBar;
|
use crate::util::progress_bar::ProgressBar;
|
||||||
use crate::util::progress_bar::ProgressBarStyle;
|
use crate::util::progress_bar::ProgressBarStyle;
|
||||||
use crate::util::v8::construct_v8_flags;
|
use crate::util::v8::construct_v8_flags;
|
||||||
|
|
Loading…
Reference in a new issue