mirror of
https://github.com/denoland/deno.git
synced 2024-12-21 23:04:45 -05:00
refactor: use concrete error types for node resolution (#24470)
This will help clean up some of the code in the CLI because we'll be able to tell how the resolution failed (not part of this PR).
This commit is contained in:
parent
07613a6bf2
commit
839caf6faf
23 changed files with 1021 additions and 599 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1771,6 +1771,7 @@ dependencies = [
|
|||
"simd-json",
|
||||
"sm3",
|
||||
"spki",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"url",
|
||||
"winapi",
|
||||
|
|
|
@ -28,13 +28,13 @@ use deno_ast::MediaType;
|
|||
use deno_cache_dir::HttpCache;
|
||||
use deno_config::workspace::PackageJsonDepResolution;
|
||||
use deno_config::workspace::WorkspaceResolver;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::url::Url;
|
||||
use deno_graph::source::Resolver;
|
||||
use deno_graph::GraphImport;
|
||||
use deno_graph::ModuleSpecifier;
|
||||
use deno_npm::NpmSystemInfo;
|
||||
use deno_runtime::deno_fs;
|
||||
use deno_runtime::deno_node::errors::ClosestPkgJsonError;
|
||||
use deno_runtime::deno_node::NodeResolution;
|
||||
use deno_runtime::deno_node::NodeResolutionMode;
|
||||
use deno_runtime::deno_node::NodeResolver;
|
||||
|
@ -365,7 +365,7 @@ impl LspResolver {
|
|||
pub fn get_closest_package_json(
|
||||
&self,
|
||||
referrer: &ModuleSpecifier,
|
||||
) -> Result<Option<Arc<PackageJson>>, AnyError> {
|
||||
) -> Result<Option<Arc<PackageJson>>, ClosestPkgJsonError> {
|
||||
let resolver = self.get_scope_resolver(Some(referrer));
|
||||
let Some(node_resolver) = resolver.node_resolver.as_ref() else {
|
||||
return Ok(None);
|
||||
|
|
|
@ -517,7 +517,7 @@ impl<TGraphContainer: ModuleGraphContainer>
|
|||
.resolve_package_sub_path_from_deno_module(
|
||||
&package_folder,
|
||||
module.nv_reference.sub_path(),
|
||||
referrer,
|
||||
Some(referrer),
|
||||
NodeResolutionMode::Execution,
|
||||
)
|
||||
.with_context(|| {
|
||||
|
|
|
@ -11,6 +11,8 @@ use deno_core::anyhow::bail;
|
|||
use deno_core::error::AnyError;
|
||||
use deno_core::serde_json;
|
||||
use deno_runtime::deno_fs::FileSystem;
|
||||
use deno_runtime::deno_node::errors::PackageFolderResolveError;
|
||||
use deno_runtime::deno_node::errors::PackageFolderResolveErrorKind;
|
||||
use deno_runtime::deno_node::load_pkg_json;
|
||||
use deno_runtime::deno_node::NodePermissions;
|
||||
use deno_runtime::deno_node::NpmResolver;
|
||||
|
@ -168,42 +170,50 @@ impl NpmResolver for ByonmCliNpmResolver {
|
|||
&self,
|
||||
name: &str,
|
||||
referrer: &ModuleSpecifier,
|
||||
) -> Result<PathBuf, AnyError> {
|
||||
) -> Result<PathBuf, PackageFolderResolveError> {
|
||||
fn inner(
|
||||
fs: &dyn FileSystem,
|
||||
name: &str,
|
||||
referrer: &ModuleSpecifier,
|
||||
) -> Result<PathBuf, AnyError> {
|
||||
let referrer_file = specifier_to_file_path(referrer)?;
|
||||
let mut current_folder = referrer_file.parent().unwrap();
|
||||
loop {
|
||||
let node_modules_folder = if current_folder.ends_with("node_modules") {
|
||||
Cow::Borrowed(current_folder)
|
||||
} else {
|
||||
Cow::Owned(current_folder.join("node_modules"))
|
||||
};
|
||||
) -> Result<PathBuf, PackageFolderResolveError> {
|
||||
let maybe_referrer_file = specifier_to_file_path(referrer).ok();
|
||||
let maybe_start_folder =
|
||||
maybe_referrer_file.as_ref().and_then(|f| f.parent());
|
||||
if let Some(start_folder) = maybe_start_folder {
|
||||
for current_folder in start_folder.ancestors() {
|
||||
let node_modules_folder = if current_folder.ends_with("node_modules")
|
||||
{
|
||||
Cow::Borrowed(current_folder)
|
||||
} else {
|
||||
Cow::Owned(current_folder.join("node_modules"))
|
||||
};
|
||||
|
||||
let sub_dir = join_package_name(&node_modules_folder, name);
|
||||
if fs.is_dir_sync(&sub_dir) {
|
||||
return Ok(sub_dir);
|
||||
}
|
||||
|
||||
if let Some(parent) = current_folder.parent() {
|
||||
current_folder = parent;
|
||||
} else {
|
||||
break;
|
||||
let sub_dir = join_package_name(&node_modules_folder, name);
|
||||
if fs.is_dir_sync(&sub_dir) {
|
||||
return Ok(sub_dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bail!(
|
||||
"could not find package '{}' from referrer '{}'.",
|
||||
name,
|
||||
referrer
|
||||
);
|
||||
Err(
|
||||
PackageFolderResolveErrorKind::NotFoundPackage {
|
||||
package_name: name.to_string(),
|
||||
referrer: referrer.clone(),
|
||||
referrer_extra: None,
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
let path = inner(&*self.fs, name, referrer)?;
|
||||
Ok(self.fs.realpath_sync(&path)?)
|
||||
self.fs.realpath_sync(&path).map_err(|err| {
|
||||
PackageFolderResolveErrorKind::Io {
|
||||
package_name: name.to_string(),
|
||||
referrer: referrer.clone(),
|
||||
source: err.into_io_error(),
|
||||
}
|
||||
.into()
|
||||
})
|
||||
}
|
||||
|
||||
fn in_npm_package(&self, specifier: &ModuleSpecifier) -> bool {
|
||||
|
|
|
@ -20,6 +20,8 @@ use deno_npm::NpmPackageId;
|
|||
use deno_npm::NpmResolutionPackage;
|
||||
use deno_npm::NpmSystemInfo;
|
||||
use deno_runtime::deno_fs::FileSystem;
|
||||
use deno_runtime::deno_node::errors::PackageFolderResolveError;
|
||||
use deno_runtime::deno_node::errors::PackageFolderResolveErrorKind;
|
||||
use deno_runtime::deno_node::NodePermissions;
|
||||
use deno_runtime::deno_node::NpmResolver;
|
||||
use deno_semver::package::PackageNv;
|
||||
|
@ -522,12 +524,17 @@ impl NpmResolver for ManagedCliNpmResolver {
|
|||
&self,
|
||||
name: &str,
|
||||
referrer: &ModuleSpecifier,
|
||||
) -> Result<PathBuf, AnyError> {
|
||||
) -> Result<PathBuf, PackageFolderResolveError> {
|
||||
let path = self
|
||||
.fs_resolver
|
||||
.resolve_package_folder_from_package(name, referrer)?;
|
||||
let path =
|
||||
canonicalize_path_maybe_not_exists_with_fs(&path, self.fs.as_ref())?;
|
||||
canonicalize_path_maybe_not_exists_with_fs(&path, self.fs.as_ref())
|
||||
.map_err(|err| PackageFolderResolveErrorKind::Io {
|
||||
package_name: name.to_string(),
|
||||
referrer: referrer.clone(),
|
||||
source: err,
|
||||
})?;
|
||||
log::debug!("Resolved {} from {} to {}", name, referrer, path.display());
|
||||
Ok(path)
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ use deno_npm::NpmPackageCacheFolderId;
|
|||
use deno_npm::NpmPackageId;
|
||||
use deno_npm::NpmResolutionPackage;
|
||||
use deno_runtime::deno_fs::FileSystem;
|
||||
use deno_runtime::deno_node::errors::PackageFolderResolveError;
|
||||
use deno_runtime::deno_node::NodePermissions;
|
||||
|
||||
use crate::npm::managed::cache::TarballCache;
|
||||
|
@ -31,16 +32,25 @@ pub trait NpmPackageFsResolver: Send + Sync {
|
|||
/// The local node_modules folder if it is applicable to the implementation.
|
||||
fn node_modules_path(&self) -> Option<&PathBuf>;
|
||||
|
||||
fn maybe_package_folder(&self, package_id: &NpmPackageId) -> Option<PathBuf>;
|
||||
|
||||
fn package_folder(
|
||||
&self,
|
||||
package_id: &NpmPackageId,
|
||||
) -> Result<PathBuf, AnyError>;
|
||||
) -> Result<PathBuf, AnyError> {
|
||||
self.maybe_package_folder(package_id).ok_or_else(|| {
|
||||
deno_core::anyhow::anyhow!(
|
||||
"Package folder not found for '{}'",
|
||||
package_id.as_serialized()
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn resolve_package_folder_from_package(
|
||||
&self,
|
||||
name: &str,
|
||||
referrer: &ModuleSpecifier,
|
||||
) -> Result<PathBuf, AnyError>;
|
||||
) -> Result<PathBuf, PackageFolderResolveError>;
|
||||
|
||||
fn resolve_package_cache_folder_id_from_specifier(
|
||||
&self,
|
||||
|
|
|
@ -8,13 +8,14 @@ use std::sync::Arc;
|
|||
|
||||
use async_trait::async_trait;
|
||||
use deno_ast::ModuleSpecifier;
|
||||
use deno_core::anyhow::bail;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::url::Url;
|
||||
use deno_npm::NpmPackageCacheFolderId;
|
||||
use deno_npm::NpmPackageId;
|
||||
use deno_npm::NpmSystemInfo;
|
||||
use deno_runtime::deno_fs::FileSystem;
|
||||
use deno_runtime::deno_node::errors::PackageFolderResolveError;
|
||||
use deno_runtime::deno_node::errors::PackageFolderResolveErrorKind;
|
||||
use deno_runtime::deno_node::NodePermissions;
|
||||
|
||||
use super::super::cache::NpmCache;
|
||||
|
@ -65,29 +66,71 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver {
|
|||
None
|
||||
}
|
||||
|
||||
fn package_folder(&self, id: &NpmPackageId) -> Result<PathBuf, AnyError> {
|
||||
fn maybe_package_folder(&self, id: &NpmPackageId) -> Option<PathBuf> {
|
||||
let folder_id = self
|
||||
.resolution
|
||||
.resolve_pkg_cache_folder_id_from_pkg_id(id)
|
||||
.unwrap();
|
||||
Ok(self.cache.package_folder_for_id(&folder_id))
|
||||
.resolve_pkg_cache_folder_id_from_pkg_id(id)?;
|
||||
Some(self.cache.package_folder_for_id(&folder_id))
|
||||
}
|
||||
|
||||
fn resolve_package_folder_from_package(
|
||||
&self,
|
||||
name: &str,
|
||||
referrer: &ModuleSpecifier,
|
||||
) -> Result<PathBuf, AnyError> {
|
||||
let Some(referrer_pkg_id) = self
|
||||
) -> Result<PathBuf, PackageFolderResolveError> {
|
||||
use deno_npm::resolution::PackageNotFoundFromReferrerError;
|
||||
let Some(referrer_cache_folder_id) = self
|
||||
.cache
|
||||
.resolve_package_folder_id_from_specifier(referrer)
|
||||
else {
|
||||
bail!("could not find npm package for '{}'", referrer);
|
||||
return Err(
|
||||
PackageFolderResolveErrorKind::NotFoundReferrer {
|
||||
referrer: referrer.clone(),
|
||||
referrer_extra: None,
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
};
|
||||
let pkg = self
|
||||
let resolve_result = self
|
||||
.resolution
|
||||
.resolve_package_from_package(name, &referrer_pkg_id)?;
|
||||
self.package_folder(&pkg.id)
|
||||
.resolve_package_from_package(name, &referrer_cache_folder_id);
|
||||
match resolve_result {
|
||||
Ok(pkg) => match self.maybe_package_folder(&pkg.id) {
|
||||
Some(folder) => Ok(folder),
|
||||
None => Err(
|
||||
PackageFolderResolveErrorKind::NotFoundPackage {
|
||||
package_name: name.to_string(),
|
||||
referrer: referrer.clone(),
|
||||
referrer_extra: Some(format!(
|
||||
"{} -> {}",
|
||||
referrer_cache_folder_id,
|
||||
pkg.id.as_serialized()
|
||||
)),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
},
|
||||
Err(err) => match *err {
|
||||
PackageNotFoundFromReferrerError::Referrer(cache_folder_id) => Err(
|
||||
PackageFolderResolveErrorKind::NotFoundReferrer {
|
||||
referrer: referrer.clone(),
|
||||
referrer_extra: Some(cache_folder_id.to_string()),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
PackageNotFoundFromReferrerError::Package {
|
||||
name,
|
||||
referrer: cache_folder_id_referrer,
|
||||
} => Err(
|
||||
PackageFolderResolveErrorKind::NotFoundPackage {
|
||||
package_name: name,
|
||||
referrer: referrer.clone(),
|
||||
referrer_extra: Some(cache_folder_id_referrer.to_string()),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_package_cache_folder_id_from_specifier(
|
||||
|
|
|
@ -15,19 +15,8 @@ use std::path::PathBuf;
|
|||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::args::PackageJsonInstallDepsProvider;
|
||||
use crate::cache::CACHE_PERM;
|
||||
use crate::npm::cache_dir::mixed_case_package_name_decode;
|
||||
use crate::util::fs::atomic_write_file_with_retries;
|
||||
use crate::util::fs::canonicalize_path_maybe_not_exists_with_fs;
|
||||
use crate::util::fs::clone_dir_recursive;
|
||||
use crate::util::fs::symlink_dir;
|
||||
use crate::util::fs::LaxSingleProcessFsFlag;
|
||||
use crate::util::progress_bar::ProgressBar;
|
||||
use crate::util::progress_bar::ProgressMessagePrompt;
|
||||
use async_trait::async_trait;
|
||||
use deno_ast::ModuleSpecifier;
|
||||
use deno_core::anyhow::bail;
|
||||
use deno_core::anyhow::Context;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::futures::stream::FuturesUnordered;
|
||||
|
@ -39,12 +28,24 @@ use deno_npm::NpmPackageId;
|
|||
use deno_npm::NpmResolutionPackage;
|
||||
use deno_npm::NpmSystemInfo;
|
||||
use deno_runtime::deno_fs;
|
||||
use deno_runtime::deno_node::errors::PackageFolderResolveError;
|
||||
use deno_runtime::deno_node::errors::PackageFolderResolveErrorKind;
|
||||
use deno_runtime::deno_node::NodePermissions;
|
||||
use deno_semver::package::PackageNv;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::args::PackageJsonInstallDepsProvider;
|
||||
use crate::cache::CACHE_PERM;
|
||||
use crate::npm::cache_dir::mixed_case_package_name_decode;
|
||||
use crate::npm::cache_dir::mixed_case_package_name_encode;
|
||||
use crate::util::fs::atomic_write_file_with_retries;
|
||||
use crate::util::fs::canonicalize_path_maybe_not_exists_with_fs;
|
||||
use crate::util::fs::clone_dir_recursive;
|
||||
use crate::util::fs::symlink_dir;
|
||||
use crate::util::fs::LaxSingleProcessFsFlag;
|
||||
use crate::util::progress_bar::ProgressBar;
|
||||
use crate::util::progress_bar::ProgressMessagePrompt;
|
||||
|
||||
use super::super::cache::NpmCache;
|
||||
use super::super::cache::TarballCache;
|
||||
|
@ -113,7 +114,7 @@ impl LocalNpmPackageResolver {
|
|||
fn resolve_folder_for_specifier(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
) -> Result<Option<PathBuf>, AnyError> {
|
||||
) -> Result<Option<PathBuf>, std::io::Error> {
|
||||
let Some(relative_url) =
|
||||
self.root_node_modules_url.make_relative(specifier)
|
||||
else {
|
||||
|
@ -130,7 +131,6 @@ impl LocalNpmPackageResolver {
|
|||
// in `node_modules` directory of the referrer.
|
||||
canonicalize_path_maybe_not_exists_with_fs(&path, self.fs.as_ref())
|
||||
.map(Some)
|
||||
.map_err(|err| err.into())
|
||||
}
|
||||
|
||||
fn resolve_package_folder_from_specifier(
|
||||
|
@ -155,32 +155,42 @@ impl NpmPackageFsResolver for LocalNpmPackageResolver {
|
|||
Some(&self.root_node_modules_path)
|
||||
}
|
||||
|
||||
fn package_folder(&self, id: &NpmPackageId) -> Result<PathBuf, AnyError> {
|
||||
match self.resolution.resolve_pkg_cache_folder_id_from_pkg_id(id) {
|
||||
// package is stored at:
|
||||
// node_modules/.deno/<package_cache_folder_id_folder_name>/node_modules/<package_name>
|
||||
Some(cache_folder_id) => Ok(
|
||||
self
|
||||
.root_node_modules_path
|
||||
.join(".deno")
|
||||
.join(get_package_folder_id_folder_name(&cache_folder_id))
|
||||
.join("node_modules")
|
||||
.join(&cache_folder_id.nv.name),
|
||||
),
|
||||
None => bail!(
|
||||
"Could not find package information for '{}'",
|
||||
id.as_serialized()
|
||||
),
|
||||
}
|
||||
fn maybe_package_folder(&self, id: &NpmPackageId) -> Option<PathBuf> {
|
||||
let cache_folder_id = self
|
||||
.resolution
|
||||
.resolve_pkg_cache_folder_id_from_pkg_id(id)?;
|
||||
// package is stored at:
|
||||
// node_modules/.deno/<package_cache_folder_id_folder_name>/node_modules/<package_name>
|
||||
Some(
|
||||
self
|
||||
.root_node_modules_path
|
||||
.join(".deno")
|
||||
.join(get_package_folder_id_folder_name(&cache_folder_id))
|
||||
.join("node_modules")
|
||||
.join(&cache_folder_id.nv.name),
|
||||
)
|
||||
}
|
||||
|
||||
fn resolve_package_folder_from_package(
|
||||
&self,
|
||||
name: &str,
|
||||
referrer: &ModuleSpecifier,
|
||||
) -> Result<PathBuf, AnyError> {
|
||||
let Some(local_path) = self.resolve_folder_for_specifier(referrer)? else {
|
||||
bail!("could not find npm package for '{}'", referrer);
|
||||
) -> Result<PathBuf, PackageFolderResolveError> {
|
||||
let maybe_local_path = self
|
||||
.resolve_folder_for_specifier(referrer)
|
||||
.map_err(|err| PackageFolderResolveErrorKind::Io {
|
||||
package_name: name.to_string(),
|
||||
referrer: referrer.clone(),
|
||||
source: err,
|
||||
})?;
|
||||
let Some(local_path) = maybe_local_path else {
|
||||
return Err(
|
||||
PackageFolderResolveErrorKind::NotFoundReferrer {
|
||||
referrer: referrer.clone(),
|
||||
referrer_extra: None,
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
};
|
||||
let package_root_path = self.resolve_package_root(&local_path);
|
||||
let mut current_folder = package_root_path.as_path();
|
||||
|
@ -202,11 +212,14 @@ impl NpmPackageFsResolver for LocalNpmPackageResolver {
|
|||
}
|
||||
}
|
||||
|
||||
bail!(
|
||||
"could not find package '{}' from referrer '{}'.",
|
||||
name,
|
||||
referrer
|
||||
);
|
||||
Err(
|
||||
PackageFolderResolveErrorKind::NotFoundPackage {
|
||||
package_name: name.to_string(),
|
||||
referrer: referrer.clone(),
|
||||
referrer_extra: None,
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
fn resolve_package_cache_folder_id_from_specifier(
|
||||
|
@ -696,6 +709,7 @@ fn junction_or_symlink_dir(
|
|||
old_path: &Path,
|
||||
new_path: &Path,
|
||||
) -> Result<(), AnyError> {
|
||||
use deno_core::anyhow::bail;
|
||||
// Use junctions because they're supported on ntfs file systems without
|
||||
// needing to elevate privileges on Windows
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@ use deno_graph::NpmResolvePkgReqsResult;
|
|||
use deno_npm::resolution::NpmResolutionError;
|
||||
use deno_runtime::deno_fs;
|
||||
use deno_runtime::deno_fs::FileSystem;
|
||||
use deno_runtime::deno_node::errors::ClosestPkgJsonError;
|
||||
use deno_runtime::deno_node::errors::UrlToNodeResolutionError;
|
||||
use deno_runtime::deno_node::is_builtin_node_module;
|
||||
use deno_runtime::deno_node::parse_npm_pkg_name;
|
||||
use deno_runtime::deno_node::NodeResolution;
|
||||
|
@ -94,7 +96,7 @@ impl CliNodeResolver {
|
|||
pub fn get_closest_package_json(
|
||||
&self,
|
||||
referrer: &ModuleSpecifier,
|
||||
) -> Result<Option<Arc<PackageJson>>, AnyError> {
|
||||
) -> Result<Option<Arc<PackageJson>>, ClosestPkgJsonError> {
|
||||
self.node_resolver.get_closest_package_json(referrer)
|
||||
}
|
||||
|
||||
|
@ -119,7 +121,10 @@ impl CliNodeResolver {
|
|||
mode: NodeResolutionMode,
|
||||
) -> Result<Option<NodeResolution>, AnyError> {
|
||||
self.handle_node_resolve_result(
|
||||
self.node_resolver.resolve(specifier, referrer, mode),
|
||||
self
|
||||
.node_resolver
|
||||
.resolve(specifier, referrer, mode)
|
||||
.map_err(AnyError::from),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -151,7 +156,7 @@ impl CliNodeResolver {
|
|||
.maybe_resolve_package_sub_path_from_deno_module(
|
||||
&package_folder,
|
||||
sub_path,
|
||||
referrer,
|
||||
Some(referrer),
|
||||
mode,
|
||||
)?;
|
||||
match maybe_resolution {
|
||||
|
@ -180,14 +185,14 @@ impl CliNodeResolver {
|
|||
&self,
|
||||
package_folder: &Path,
|
||||
sub_path: Option<&str>,
|
||||
referrer: &ModuleSpecifier,
|
||||
maybe_referrer: Option<&ModuleSpecifier>,
|
||||
mode: NodeResolutionMode,
|
||||
) -> Result<NodeResolution, AnyError> {
|
||||
self
|
||||
.maybe_resolve_package_sub_path_from_deno_module(
|
||||
package_folder,
|
||||
sub_path,
|
||||
referrer,
|
||||
maybe_referrer,
|
||||
mode,
|
||||
)?
|
||||
.ok_or_else(|| {
|
||||
|
@ -205,16 +210,19 @@ impl CliNodeResolver {
|
|||
&self,
|
||||
package_folder: &Path,
|
||||
sub_path: Option<&str>,
|
||||
referrer: &ModuleSpecifier,
|
||||
maybe_referrer: Option<&ModuleSpecifier>,
|
||||
mode: NodeResolutionMode,
|
||||
) -> Result<Option<NodeResolution>, AnyError> {
|
||||
self.handle_node_resolve_result(
|
||||
self.node_resolver.resolve_package_subpath_from_deno_module(
|
||||
package_folder,
|
||||
sub_path,
|
||||
referrer,
|
||||
mode,
|
||||
),
|
||||
self
|
||||
.node_resolver
|
||||
.resolve_package_subpath_from_deno_module(
|
||||
package_folder,
|
||||
sub_path,
|
||||
maybe_referrer,
|
||||
mode,
|
||||
)
|
||||
.map_err(AnyError::from),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -252,7 +260,7 @@ impl CliNodeResolver {
|
|||
pub fn url_to_node_resolution(
|
||||
&self,
|
||||
specifier: ModuleSpecifier,
|
||||
) -> Result<NodeResolution, AnyError> {
|
||||
) -> Result<NodeResolution, UrlToNodeResolutionError> {
|
||||
self.node_resolver.url_to_node_resolution(specifier)
|
||||
}
|
||||
|
||||
|
@ -574,7 +582,7 @@ impl Resolver for CliGraphResolver {
|
|||
.resolve_package_sub_path_from_deno_module(
|
||||
pkg_folder,
|
||||
sub_path.as_deref(),
|
||||
referrer,
|
||||
Some(referrer),
|
||||
to_node_mode(mode),
|
||||
)?
|
||||
.into_url(),
|
||||
|
@ -599,7 +607,7 @@ impl Resolver for CliGraphResolver {
|
|||
.resolve_package_sub_path_from_deno_module(
|
||||
pkg_folder,
|
||||
req_ref.sub_path(),
|
||||
referrer,
|
||||
Some(referrer),
|
||||
to_node_mode(mode),
|
||||
)?
|
||||
.into_url(),
|
||||
|
|
|
@ -197,7 +197,7 @@ impl ModuleLoader for EmbeddedModuleLoader {
|
|||
.resolve_package_sub_path_from_deno_module(
|
||||
pkg_folder,
|
||||
sub_path.as_deref(),
|
||||
&referrer,
|
||||
Some(&referrer),
|
||||
NodeResolutionMode::Execution,
|
||||
)?
|
||||
.into_url(),
|
||||
|
|
|
@ -739,7 +739,7 @@ fn resolve_graph_specifier_types(
|
|||
npm.node_resolver.resolve_package_subpath_from_deno_module(
|
||||
&package_folder,
|
||||
module.nv_reference.sub_path(),
|
||||
referrer,
|
||||
Some(referrer),
|
||||
NodeResolutionMode::Types,
|
||||
)?;
|
||||
Ok(Some(NodeResolution::into_specifier_and_media_type(
|
||||
|
@ -793,7 +793,7 @@ fn resolve_non_graph_specifier_types(
|
|||
.resolve_package_subpath_from_deno_module(
|
||||
&package_folder,
|
||||
npm_req_ref.sub_path(),
|
||||
referrer,
|
||||
Some(referrer),
|
||||
NodeResolutionMode::Types,
|
||||
)?;
|
||||
Ok(Some(NodeResolution::into_specifier_and_media_type(
|
||||
|
|
|
@ -669,7 +669,7 @@ impl CliMainWorkerFactory {
|
|||
self.resolve_binary_entrypoint_fallback(package_folder, sub_path);
|
||||
match result {
|
||||
Ok(Some(resolution)) => Ok(resolution),
|
||||
Ok(None) => Err(original_err),
|
||||
Ok(None) => Err(original_err.into()),
|
||||
Err(fallback_err) => {
|
||||
bail!("{:#}\n\nFallback failed: {:#}", original_err, fallback_err)
|
||||
}
|
||||
|
@ -692,16 +692,13 @@ impl CliMainWorkerFactory {
|
|||
return Ok(None);
|
||||
}
|
||||
|
||||
// use a fake referrer since a real one doesn't exist
|
||||
let referrer =
|
||||
ModuleSpecifier::from_directory_path(package_folder).unwrap();
|
||||
let Some(resolution) = self
|
||||
.shared
|
||||
.node_resolver
|
||||
.resolve_package_subpath_from_deno_module(
|
||||
package_folder,
|
||||
sub_path,
|
||||
&referrer,
|
||||
/* referrer */ None,
|
||||
NodeResolutionMode::Execution,
|
||||
)?
|
||||
else {
|
||||
|
|
|
@ -350,7 +350,7 @@ impl<'a> deno_config::fs::DenoConfigFs for DenoConfigFsAdapter<'a> {
|
|||
self
|
||||
.0
|
||||
.read_text_file_lossy_sync(path, None)
|
||||
.map_err(map_deno_fs_to_config_err)
|
||||
.map_err(|err| err.into_io_error())
|
||||
}
|
||||
|
||||
fn stat_sync(
|
||||
|
@ -365,7 +365,7 @@ impl<'a> deno_config::fs::DenoConfigFs for DenoConfigFsAdapter<'a> {
|
|||
is_directory: stat.is_directory,
|
||||
is_symlink: stat.is_symlink,
|
||||
})
|
||||
.map_err(map_deno_fs_to_config_err)
|
||||
.map_err(|err| err.into_io_error())
|
||||
}
|
||||
|
||||
fn read_dir(
|
||||
|
@ -375,7 +375,7 @@ impl<'a> deno_config::fs::DenoConfigFs for DenoConfigFsAdapter<'a> {
|
|||
self
|
||||
.0
|
||||
.read_dir_sync(path)
|
||||
.map_err(map_deno_fs_to_config_err)
|
||||
.map_err(|err| err.into_io_error())
|
||||
.map(|entries| {
|
||||
entries
|
||||
.into_iter()
|
||||
|
@ -392,22 +392,6 @@ impl<'a> deno_config::fs::DenoConfigFs for DenoConfigFsAdapter<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn map_deno_fs_to_config_err(fs_err: deno_io::fs::FsError) -> std::io::Error {
|
||||
use deno_io::fs::FsError;
|
||||
use std::io::ErrorKind;
|
||||
match fs_err {
|
||||
FsError::Io(io) => io,
|
||||
FsError::FileBusy => std::io::Error::new(ErrorKind::Other, "file busy"),
|
||||
FsError::NotSupported => {
|
||||
std::io::Error::new(ErrorKind::Other, "not supported")
|
||||
}
|
||||
FsError::PermissionDenied(name) => std::io::Error::new(
|
||||
ErrorKind::PermissionDenied,
|
||||
format!("requires {}", name),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
// Like String::from_utf8_lossy but operates on owned values
|
||||
#[inline(always)]
|
||||
fn string_from_utf8_lossy(buf: Vec<u8>) -> String {
|
||||
|
|
|
@ -78,6 +78,7 @@ signature.workspace = true
|
|||
simd-json = "0.13.4"
|
||||
sm3 = "0.4.2"
|
||||
spki.workspace = true
|
||||
thiserror.workspace = true
|
||||
tokio.workspace = true
|
||||
url.workspace = true
|
||||
winapi.workspace = true
|
||||
|
|
|
@ -278,6 +278,7 @@ impl<TCjsCodeAnalyzer: CjsCodeAnalyzer> NodeCodeTranslator<TCjsCodeAnalyzer> {
|
|||
}
|
||||
}
|
||||
|
||||
// todo(dsherret): what is going on here? Isn't this a bunch of duplicate code?
|
||||
fn resolve(
|
||||
&self,
|
||||
specifier: &str,
|
||||
|
@ -314,15 +315,18 @@ impl<TCjsCodeAnalyzer: CjsCodeAnalyzer> NodeCodeTranslator<TCjsCodeAnalyzer> {
|
|||
let maybe_package_json = load_pkg_json(&*self.fs, &package_json_path)?;
|
||||
if let Some(package_json) = maybe_package_json {
|
||||
if let Some(exports) = &package_json.exports {
|
||||
return self.node_resolver.package_exports_resolve(
|
||||
&package_json_path,
|
||||
&package_subpath,
|
||||
exports,
|
||||
referrer,
|
||||
NodeModuleKind::Esm,
|
||||
conditions,
|
||||
mode,
|
||||
);
|
||||
return self
|
||||
.node_resolver
|
||||
.package_exports_resolve(
|
||||
&package_json_path,
|
||||
&package_subpath,
|
||||
exports,
|
||||
Some(referrer),
|
||||
NodeModuleKind::Esm,
|
||||
conditions,
|
||||
mode,
|
||||
)
|
||||
.map_err(AnyError::from);
|
||||
}
|
||||
|
||||
// old school
|
||||
|
|
|
@ -1,28 +1,443 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use deno_core::error::generic_error;
|
||||
use deno_core::error::type_error;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::url::Url;
|
||||
use deno_core::ModuleSpecifier;
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::NodeModuleKind;
|
||||
use crate::NodeResolutionMode;
|
||||
|
||||
pub fn err_invalid_module_specifier(
|
||||
request: &str,
|
||||
reason: &str,
|
||||
maybe_base: Option<String>,
|
||||
) -> AnyError {
|
||||
let mut msg = format!(
|
||||
"[ERR_INVALID_MODULE_SPECIFIER] Invalid module \"{request}\" {reason}"
|
||||
);
|
||||
macro_rules! kinded_err {
|
||||
($name:ident, $kind_name:ident) => {
|
||||
#[derive(Error, Debug)]
|
||||
#[error(transparent)]
|
||||
pub struct $name(pub Box<$kind_name>);
|
||||
|
||||
if let Some(base) = maybe_base {
|
||||
msg = format!("{msg} imported from {base}");
|
||||
impl $name {
|
||||
pub fn as_kind(&self) -> &$kind_name {
|
||||
&self.0
|
||||
}
|
||||
|
||||
pub fn into_kind(self) -> $kind_name {
|
||||
*self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> From<E> for $name
|
||||
where
|
||||
$kind_name: From<E>,
|
||||
{
|
||||
fn from(err: E) -> Self {
|
||||
$name(Box::new($kind_name::from(err)))
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
kinded_err!(
|
||||
ResolvePkgSubpathFromDenoModuleError,
|
||||
ResolvePkgSubpathFromDenoModuleErrorKind
|
||||
);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ResolvePkgSubpathFromDenoModuleErrorKind {
|
||||
#[error(transparent)]
|
||||
PackageSubpathResolve(#[from] PackageSubpathResolveError),
|
||||
#[error(transparent)]
|
||||
UrlToNodeResolution(#[from] UrlToNodeResolutionError),
|
||||
}
|
||||
|
||||
// todo(https://github.com/denoland/deno_core/issues/810): make this a TypeError
|
||||
#[derive(Debug, Clone, Error)]
|
||||
#[error(
|
||||
"[ERR_INVALID_MODULE_SPECIFIER] Invalid module '{}' {}{}",
|
||||
request,
|
||||
reason,
|
||||
maybe_referrer.as_ref().map(|referrer| format!(" imported from '{}'", referrer)).unwrap_or_default()
|
||||
)]
|
||||
pub struct InvalidModuleSpecifierError {
|
||||
pub request: String,
|
||||
pub reason: Cow<'static, str>,
|
||||
pub maybe_referrer: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum LegacyMainResolveError {
|
||||
#[error(transparent)]
|
||||
PathToDeclarationUrl(PathToDeclarationUrlError),
|
||||
}
|
||||
|
||||
kinded_err!(PackageFolderResolveError, PackageFolderResolveErrorKind);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum PackageFolderResolveErrorKind {
|
||||
#[error(
|
||||
"Could not find package '{}' from referrer '{}'{}.",
|
||||
package_name,
|
||||
referrer,
|
||||
referrer_extra.as_ref().map(|r| format!(" ({})", r)).unwrap_or_default()
|
||||
)]
|
||||
NotFoundPackage {
|
||||
package_name: String,
|
||||
referrer: ModuleSpecifier,
|
||||
/// Extra information about the referrer.
|
||||
referrer_extra: Option<String>,
|
||||
},
|
||||
#[error(
|
||||
"Could not find referrer npm package '{}'{}.",
|
||||
referrer,
|
||||
referrer_extra.as_ref().map(|r| format!(" ({})", r)).unwrap_or_default()
|
||||
)]
|
||||
NotFoundReferrer {
|
||||
referrer: ModuleSpecifier,
|
||||
/// Extra information about the referrer.
|
||||
referrer_extra: Option<String>,
|
||||
},
|
||||
#[error("Failed resolving '{package_name}' from referrer '{referrer}'.")]
|
||||
Io {
|
||||
package_name: String,
|
||||
referrer: ModuleSpecifier,
|
||||
#[source]
|
||||
source: std::io::Error,
|
||||
},
|
||||
}
|
||||
|
||||
kinded_err!(PackageSubpathResolveError, PackageSubpathResolveErrorKind);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum PackageSubpathResolveErrorKind {
|
||||
#[error(transparent)]
|
||||
PkgJsonLoad(#[from] deno_config::package_json::PackageJsonLoadError),
|
||||
#[error(transparent)]
|
||||
PackageFolderResolve(#[from] PackageFolderResolveError),
|
||||
#[error(transparent)]
|
||||
DirNotFound(AnyError),
|
||||
#[error(transparent)]
|
||||
Exports(PackageExportsResolveError),
|
||||
#[error(transparent)]
|
||||
LegacyMain(LegacyMainResolveError),
|
||||
#[error(transparent)]
|
||||
LegacyExact(PathToDeclarationUrlError),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
#[error(
|
||||
"Target '{}' not found from '{}'{}{}.",
|
||||
target,
|
||||
pkg_json_path.display(),
|
||||
maybe_referrer.as_ref().map(|r|
|
||||
format!(
|
||||
" from{} referrer {}",
|
||||
match referrer_kind {
|
||||
NodeModuleKind::Esm => "",
|
||||
NodeModuleKind::Cjs => " cjs",
|
||||
},
|
||||
r
|
||||
)
|
||||
).unwrap_or_default(),
|
||||
match mode {
|
||||
NodeResolutionMode::Execution => "",
|
||||
NodeResolutionMode::Types => " for types",
|
||||
}
|
||||
)]
|
||||
pub struct PackageTargetNotFoundError {
|
||||
pub pkg_json_path: PathBuf,
|
||||
pub target: String,
|
||||
pub maybe_referrer: Option<ModuleSpecifier>,
|
||||
pub referrer_kind: NodeModuleKind,
|
||||
pub mode: NodeResolutionMode,
|
||||
}
|
||||
|
||||
type_error(msg)
|
||||
kinded_err!(PackageTargetResolveError, PackageTargetResolveErrorKind);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum PackageTargetResolveErrorKind {
|
||||
#[error(transparent)]
|
||||
NotFound(#[from] PackageTargetNotFoundError),
|
||||
#[error(transparent)]
|
||||
InvalidPackageTarget(#[from] InvalidPackageTargetError),
|
||||
#[error(transparent)]
|
||||
InvalidModuleSpecifier(#[from] InvalidModuleSpecifierError),
|
||||
#[error(transparent)]
|
||||
PackageResolve(#[from] PackageResolveError),
|
||||
#[error(transparent)]
|
||||
PathToDeclarationUrl(#[from] PathToDeclarationUrlError),
|
||||
}
|
||||
|
||||
kinded_err!(PackageExportsResolveError, PackageExportsResolveErrorKind);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum PackageExportsResolveErrorKind {
|
||||
#[error(transparent)]
|
||||
PackagePathNotExported(#[from] PackagePathNotExportedError),
|
||||
#[error(transparent)]
|
||||
PackageTargetResolve(#[from] PackageTargetResolveError),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum PathToDeclarationUrlError {
|
||||
#[error(transparent)]
|
||||
SubPath(#[from] PackageSubpathResolveError),
|
||||
}
|
||||
|
||||
kinded_err!(ClosestPkgJsonError, ClosestPkgJsonErrorKind);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ClosestPkgJsonErrorKind {
|
||||
#[error("Failed canonicalizing package.json directory '{dir_path}'.")]
|
||||
CanonicalizingDir {
|
||||
dir_path: PathBuf,
|
||||
#[source]
|
||||
source: std::io::Error,
|
||||
},
|
||||
#[error(transparent)]
|
||||
Load(#[from] deno_config::package_json::PackageJsonLoadError),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
#[error("TypeScript files are not supported in npm packages: {specifier}")]
|
||||
pub struct TypeScriptNotSupportedInNpmError {
|
||||
pub specifier: ModuleSpecifier,
|
||||
}
|
||||
|
||||
kinded_err!(UrlToNodeResolutionError, UrlToNodeResolutionErrorKind);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum UrlToNodeResolutionErrorKind {
|
||||
#[error(transparent)]
|
||||
TypeScriptNotSupported(#[from] TypeScriptNotSupportedInNpmError),
|
||||
#[error(transparent)]
|
||||
ClosestPkgJson(#[from] ClosestPkgJsonError),
|
||||
}
|
||||
|
||||
// todo(https://github.com/denoland/deno_core/issues/810): make this a TypeError
|
||||
#[derive(Debug, Error)]
|
||||
#[error(
|
||||
"[ERR_PACKAGE_IMPORT_NOT_DEFINED] Package import specifier \"{}\" is not defined{}{}",
|
||||
name,
|
||||
package_json_path.as_ref().map(|p| format!(" in package {}", p.display())).unwrap_or_default(),
|
||||
maybe_referrer.as_ref().map(|r| format!(" imported from '{}'", r)).unwrap_or_default(),
|
||||
)]
|
||||
pub struct PackageImportNotDefinedError {
|
||||
pub name: String,
|
||||
pub package_json_path: Option<PathBuf>,
|
||||
pub maybe_referrer: Option<ModuleSpecifier>,
|
||||
}
|
||||
|
||||
kinded_err!(PackageImportsResolveError, PackageImportsResolveErrorKind);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum PackageImportsResolveErrorKind {
|
||||
#[error(transparent)]
|
||||
ClosestPkgJson(ClosestPkgJsonError),
|
||||
#[error(transparent)]
|
||||
InvalidModuleSpecifier(#[from] InvalidModuleSpecifierError),
|
||||
#[error(transparent)]
|
||||
NotDefined(#[from] PackageImportNotDefinedError),
|
||||
#[error(transparent)]
|
||||
Target(#[from] PackageTargetResolveError),
|
||||
}
|
||||
|
||||
kinded_err!(PackageResolveError, PackageResolveErrorKind);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum PackageResolveErrorKind {
|
||||
#[error(transparent)]
|
||||
ClosestPkgJson(#[from] ClosestPkgJsonError),
|
||||
#[error(transparent)]
|
||||
InvalidModuleSpecifier(#[from] InvalidModuleSpecifierError),
|
||||
#[error(transparent)]
|
||||
ExportsResolve(#[from] PackageExportsResolveError),
|
||||
#[error(transparent)]
|
||||
SubpathResolve(#[from] PackageSubpathResolveError),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum NodeResolveError {
|
||||
#[error("Failed joining '{path}' from '{base}'.")]
|
||||
RelativeJoinError {
|
||||
path: String,
|
||||
base: ModuleSpecifier,
|
||||
#[source]
|
||||
source: url::ParseError,
|
||||
},
|
||||
#[error(transparent)]
|
||||
PackageImportsResolve(#[from] PackageImportsResolveError),
|
||||
#[error(transparent)]
|
||||
UnsupportedEsmUrlScheme(#[from] UnsupportedEsmUrlSchemeError),
|
||||
#[error("Failed resolving specifier from data url referrer.")]
|
||||
DataUrlReferrerFailed {
|
||||
#[source]
|
||||
source: url::ParseError,
|
||||
},
|
||||
#[error(transparent)]
|
||||
PackageResolve(#[from] PackageResolveError),
|
||||
#[error(transparent)]
|
||||
PathToDeclarationUrl(#[from] PathToDeclarationUrlError),
|
||||
#[error(transparent)]
|
||||
UrlToNodeResolution(#[from] UrlToNodeResolutionError),
|
||||
#[error(transparent)]
|
||||
FinalizeResolution(#[from] FinalizeResolutionError),
|
||||
}
|
||||
|
||||
kinded_err!(FinalizeResolutionError, FinalizeResolutionErrorKind);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum FinalizeResolutionErrorKind {
|
||||
#[error(transparent)]
|
||||
InvalidModuleSpecifierError(#[from] InvalidModuleSpecifierError),
|
||||
#[error(transparent)]
|
||||
ModuleNotFound(#[from] ModuleNotFoundError),
|
||||
#[error(transparent)]
|
||||
UnsupportedDirImport(#[from] UnsupportedDirImportError),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
#[error(
|
||||
"[ERR_MODULE_NOT_FOUND] Cannot find {} '{}'{}",
|
||||
typ,
|
||||
specifier,
|
||||
maybe_referrer.as_ref().map(|referrer| format!(" imported from '{}'", referrer)).unwrap_or_default()
|
||||
)]
|
||||
pub struct ModuleNotFoundError {
|
||||
pub specifier: ModuleSpecifier,
|
||||
pub maybe_referrer: Option<ModuleSpecifier>,
|
||||
pub typ: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
#[error(
|
||||
"[ERR_UNSUPPORTED_DIR_IMPORT] Directory import '{}' is not supported resolving ES modules{}",
|
||||
dir_url,
|
||||
maybe_referrer.as_ref().map(|referrer| format!(" imported from '{}'", referrer)).unwrap_or_default(),
|
||||
)]
|
||||
pub struct UnsupportedDirImportError {
|
||||
pub dir_url: ModuleSpecifier,
|
||||
pub maybe_referrer: Option<ModuleSpecifier>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InvalidPackageTargetError {
|
||||
pub pkg_json_path: PathBuf,
|
||||
pub sub_path: String,
|
||||
pub target: String,
|
||||
pub is_import: bool,
|
||||
pub maybe_referrer: Option<ModuleSpecifier>,
|
||||
}
|
||||
|
||||
impl std::error::Error for InvalidPackageTargetError {}
|
||||
|
||||
impl std::fmt::Display for InvalidPackageTargetError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let rel_error = !self.is_import
|
||||
&& !self.target.is_empty()
|
||||
&& !self.target.starts_with("./");
|
||||
f.write_str("[ERR_INVALID_PACKAGE_TARGET]")?;
|
||||
|
||||
if self.sub_path == "." {
|
||||
assert!(!self.is_import);
|
||||
write!(
|
||||
f,
|
||||
" Invalid \"exports\" main target {} defined in the package config {}",
|
||||
self.target,
|
||||
self.pkg_json_path.display()
|
||||
)?;
|
||||
} else {
|
||||
let ie = if self.is_import { "imports" } else { "exports" };
|
||||
write!(
|
||||
f,
|
||||
" Invalid \"{}\" target {} defined for '{}' in the package config {}",
|
||||
ie,
|
||||
self.target,
|
||||
self.sub_path,
|
||||
self.pkg_json_path.display()
|
||||
)?;
|
||||
};
|
||||
|
||||
if let Some(referrer) = &self.maybe_referrer {
|
||||
write!(f, " imported from '{}'", referrer)?;
|
||||
}
|
||||
if rel_error {
|
||||
write!(f, "; target must start with \"./\"")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PackagePathNotExportedError {
|
||||
pub pkg_json_path: PathBuf,
|
||||
pub subpath: String,
|
||||
pub maybe_referrer: Option<ModuleSpecifier>,
|
||||
pub mode: NodeResolutionMode,
|
||||
}
|
||||
|
||||
impl std::error::Error for PackagePathNotExportedError {}
|
||||
|
||||
impl std::fmt::Display for PackagePathNotExportedError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str("[ERR_PACKAGE_PATH_NOT_EXPORTED]")?;
|
||||
|
||||
let types_msg = match self.mode {
|
||||
NodeResolutionMode::Execution => String::new(),
|
||||
NodeResolutionMode::Types => " for types".to_string(),
|
||||
};
|
||||
if self.subpath == "." {
|
||||
write!(
|
||||
f,
|
||||
" No \"exports\" main defined{} in '{}'",
|
||||
types_msg,
|
||||
self.pkg_json_path.display()
|
||||
)?;
|
||||
} else {
|
||||
write!(
|
||||
f,
|
||||
" Package subpath '{}' is not defined{} by \"exports\" in '{}'",
|
||||
self.subpath,
|
||||
types_msg,
|
||||
self.pkg_json_path.display()
|
||||
)?;
|
||||
};
|
||||
|
||||
if let Some(referrer) = &self.maybe_referrer {
|
||||
write!(f, " imported from '{}'", referrer)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Error)]
|
||||
#[error(
|
||||
"[ERR_UNSUPPORTED_ESM_URL_SCHEME] Only file and data URLS are supported by the default ESM loader.{} Received protocol '{}'",
|
||||
if cfg!(windows) && url_scheme.len() == 2 { " On Windows, absolute path must be valid file:// URLS."} else { "" },
|
||||
url_scheme
|
||||
)]
|
||||
pub struct UnsupportedEsmUrlSchemeError {
|
||||
pub url_scheme: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ResolvePkgJsonBinExportError {
|
||||
#[error(transparent)]
|
||||
PkgJsonLoad(#[from] deno_config::package_json::PackageJsonLoadError),
|
||||
#[error("Failed resolving binary export. '{}' did not exist", pkg_json_path.display())]
|
||||
MissingPkgJson { pkg_json_path: PathBuf },
|
||||
#[error("Failed resolving binary export. {message}")]
|
||||
InvalidBinProperty { message: String },
|
||||
#[error(transparent)]
|
||||
UrlToNodeResolution(#[from] UrlToNodeResolutionError),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ResolveBinaryCommandsError {
|
||||
#[error(transparent)]
|
||||
PkgJsonLoad(#[from] deno_config::package_json::PackageJsonLoadError),
|
||||
#[error("'{}' did not have a name", pkg_json_path.display())]
|
||||
MissingPkgJsonName { pkg_json_path: PathBuf },
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
|
@ -45,129 +460,6 @@ pub fn err_invalid_package_config(
|
|||
generic_error(msg)
|
||||
}
|
||||
|
||||
pub fn err_module_not_found(path: &str, base: &str, typ: &str) -> AnyError {
|
||||
generic_error(format!(
|
||||
"[ERR_MODULE_NOT_FOUND] Cannot find {typ} \"{path}\" imported from \"{base}\""
|
||||
))
|
||||
}
|
||||
|
||||
pub fn err_invalid_package_target(
|
||||
pkg_path: &str,
|
||||
key: &str,
|
||||
target: &str,
|
||||
is_import: bool,
|
||||
maybe_referrer: Option<String>,
|
||||
) -> AnyError {
|
||||
let rel_error = !is_import && !target.is_empty() && !target.starts_with("./");
|
||||
let mut msg = "[ERR_INVALID_PACKAGE_TARGET]".to_string();
|
||||
let pkg_json_path = PathBuf::from(pkg_path).join("package.json");
|
||||
|
||||
if key == "." {
|
||||
assert!(!is_import);
|
||||
msg = format!(
|
||||
"{} Invalid \"exports\" main target {} defined in the package config {}",
|
||||
msg,
|
||||
target,
|
||||
pkg_json_path.display()
|
||||
)
|
||||
} else {
|
||||
let ie = if is_import { "imports" } else { "exports" };
|
||||
msg = format!(
|
||||
"{} Invalid \"{}\" target {} defined for '{}' in the package config {}",
|
||||
msg,
|
||||
ie,
|
||||
target,
|
||||
key,
|
||||
pkg_json_path.display()
|
||||
)
|
||||
};
|
||||
|
||||
if let Some(base) = maybe_referrer {
|
||||
msg = format!("{msg} imported from {base}");
|
||||
};
|
||||
if rel_error {
|
||||
msg = format!("{msg}; target must start with \"./\"");
|
||||
}
|
||||
|
||||
generic_error(msg)
|
||||
}
|
||||
|
||||
pub fn err_package_path_not_exported(
|
||||
mut pkg_path: String,
|
||||
subpath: &str,
|
||||
maybe_referrer: Option<String>,
|
||||
mode: NodeResolutionMode,
|
||||
) -> AnyError {
|
||||
let mut msg = "[ERR_PACKAGE_PATH_NOT_EXPORTED]".to_string();
|
||||
|
||||
#[cfg(windows)]
|
||||
{
|
||||
if !pkg_path.ends_with('\\') {
|
||||
pkg_path.push('\\');
|
||||
}
|
||||
}
|
||||
#[cfg(not(windows))]
|
||||
{
|
||||
if !pkg_path.ends_with('/') {
|
||||
pkg_path.push('/');
|
||||
}
|
||||
}
|
||||
|
||||
let types_msg = match mode {
|
||||
NodeResolutionMode::Execution => String::new(),
|
||||
NodeResolutionMode::Types => " for types".to_string(),
|
||||
};
|
||||
if subpath == "." {
|
||||
msg =
|
||||
format!("{msg} No \"exports\" main defined{types_msg} in '{pkg_path}package.json'");
|
||||
} else {
|
||||
msg = format!("{msg} Package subpath '{subpath}' is not defined{types_msg} by \"exports\" in '{pkg_path}package.json'");
|
||||
};
|
||||
|
||||
if let Some(referrer) = maybe_referrer {
|
||||
msg = format!("{msg} imported from '{referrer}'");
|
||||
}
|
||||
|
||||
generic_error(msg)
|
||||
}
|
||||
|
||||
pub fn err_package_import_not_defined(
|
||||
specifier: &str,
|
||||
package_path: Option<String>,
|
||||
base: &str,
|
||||
) -> AnyError {
|
||||
let mut msg = format!(
|
||||
"[ERR_PACKAGE_IMPORT_NOT_DEFINED] Package import specifier \"{specifier}\" is not defined"
|
||||
);
|
||||
|
||||
if let Some(package_path) = package_path {
|
||||
let pkg_json_path = PathBuf::from(package_path).join("package.json");
|
||||
msg = format!("{} in package {}", msg, pkg_json_path.display());
|
||||
}
|
||||
|
||||
msg = format!("{msg} imported from {base}");
|
||||
|
||||
type_error(msg)
|
||||
}
|
||||
|
||||
pub fn err_unsupported_dir_import(path: &str, base: &str) -> AnyError {
|
||||
generic_error(format!("[ERR_UNSUPPORTED_DIR_IMPORT] Directory import '{path}' is not supported resolving ES modules imported from {base}"))
|
||||
}
|
||||
|
||||
pub fn err_unsupported_esm_url_scheme(url: &Url) -> AnyError {
|
||||
let mut msg =
|
||||
"[ERR_UNSUPPORTED_ESM_URL_SCHEME] Only file and data URLS are supported by the default ESM loader"
|
||||
.to_string();
|
||||
|
||||
if cfg!(window) && url.scheme().len() == 2 {
|
||||
msg =
|
||||
format!("{msg}. On Windows, absolute path must be valid file:// URLs");
|
||||
}
|
||||
|
||||
msg = format!("{}. Received protocol '{}'", msg, url.scheme());
|
||||
generic_error(msg)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
@ -176,23 +468,21 @@ mod test {
|
|||
fn types_resolution_package_path_not_exported() {
|
||||
let separator_char = if cfg!(windows) { '\\' } else { '/' };
|
||||
assert_eq!(
|
||||
err_package_path_not_exported(
|
||||
"test_path".to_string(),
|
||||
"./jsx-runtime",
|
||||
None,
|
||||
NodeResolutionMode::Types,
|
||||
)
|
||||
.to_string(),
|
||||
PackagePathNotExportedError {
|
||||
pkg_json_path: PathBuf::from("test_path").join("package.json"),
|
||||
subpath: "./jsx-runtime".to_string(),
|
||||
maybe_referrer: None,
|
||||
mode: NodeResolutionMode::Types
|
||||
}.to_string(),
|
||||
format!("[ERR_PACKAGE_PATH_NOT_EXPORTED] Package subpath './jsx-runtime' is not defined for types by \"exports\" in 'test_path{separator_char}package.json'")
|
||||
);
|
||||
assert_eq!(
|
||||
err_package_path_not_exported(
|
||||
"test_path".to_string(),
|
||||
".",
|
||||
None,
|
||||
NodeResolutionMode::Types,
|
||||
)
|
||||
.to_string(),
|
||||
PackagePathNotExportedError {
|
||||
pkg_json_path: PathBuf::from("test_path").join("package.json"),
|
||||
subpath: ".".to_string(),
|
||||
maybe_referrer: None,
|
||||
mode: NodeResolutionMode::Types
|
||||
}.to_string(),
|
||||
format!("[ERR_PACKAGE_PATH_NOT_EXPORTED] No \"exports\" main defined for types in 'test_path{separator_char}package.json'")
|
||||
);
|
||||
}
|
||||
|
|
|
@ -168,7 +168,7 @@ pub trait NpmResolver: std::fmt::Debug + MaybeSend + MaybeSync {
|
|||
&self,
|
||||
specifier: &str,
|
||||
referrer: &ModuleSpecifier,
|
||||
) -> Result<PathBuf, AnyError>;
|
||||
) -> Result<PathBuf, errors::PackageFolderResolveError>;
|
||||
|
||||
fn in_npm_package(&self, specifier: &ModuleSpecifier) -> bool;
|
||||
|
||||
|
|
|
@ -421,7 +421,7 @@ where
|
|||
&pkg.path,
|
||||
&expansion,
|
||||
exports,
|
||||
&referrer,
|
||||
Some(&referrer),
|
||||
NodeModuleKind::Cjs,
|
||||
resolution::REQUIRE_CONDITIONS,
|
||||
NodeResolutionMode::Execution,
|
||||
|
@ -509,7 +509,7 @@ where
|
|||
&pkg.path,
|
||||
&format!(".{expansion}"),
|
||||
exports,
|
||||
&referrer,
|
||||
Some(&referrer),
|
||||
NodeModuleKind::Cjs,
|
||||
resolution::REQUIRE_CONDITIONS,
|
||||
NodeResolutionMode::Execution,
|
||||
|
@ -538,6 +538,7 @@ where
|
|||
node_resolver
|
||||
.get_closest_package_json(&Url::from_file_path(filename).unwrap())
|
||||
.map(|maybe_pkg| maybe_pkg.map(|pkg| (*pkg).clone()))
|
||||
.map_err(AnyError::from)
|
||||
}
|
||||
|
||||
#[op2]
|
||||
|
@ -586,7 +587,7 @@ where
|
|||
deno_core::url::Url::from_file_path(&referrer_filename).unwrap();
|
||||
let url = node_resolver.package_imports_resolve(
|
||||
&request,
|
||||
&referrer_url,
|
||||
Some(&referrer_url),
|
||||
NodeModuleKind::Cjs,
|
||||
Some(&pkg),
|
||||
resolution::REQUIRE_CONDITIONS,
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1 +1 @@
|
|||
error: '[WILDCARD]@denotest[WILDCARD]esm-basic[WILDCARD]package.json' did not have a bin property
|
||||
error: Failed resolving binary export. '[WILDCARD]@denotest[WILDCARD]esm-basic[WILDCARD]package.json' did not have a bin property
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
error: '[WILDCARD]@denotest[WILDCARD]esm-basic[WILDCARD]package.json' did not have a bin property
|
||||
error: Failed resolving binary export. '[WILDCARD]@denotest[WILDCARD]esm-basic[WILDCARD]package.json' did not have a bin property
|
||||
|
||||
Fallback failed: Cannot find module 'file:///[WILDCARD]/non-existent.js'
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
Download http://localhost:4260/@denotest/imports-package-json
|
||||
Download http://localhost:4260/@denotest/imports-package-json/1.0.0.tgz
|
||||
error: [ERR_PACKAGE_IMPORT_NOT_DEFINED] Package import specifier "#not-defined" is not defined in package [WILDCARD]package.json imported from [WILDCARD]import_not_defined.js
|
||||
error: [ERR_PACKAGE_IMPORT_NOT_DEFINED] Package import specifier "#not-defined" is not defined in package [WILDCARD]package.json imported from '[WILDCARD]import_not_defined.js'
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
Download http://localhost:4260/@denotest/imports-package-json
|
||||
Download http://localhost:4260/@denotest/imports-package-json/1.0.0.tgz
|
||||
error: [ERR_PACKAGE_IMPORT_NOT_DEFINED] Package import specifier "#hi" is not defined in package [WILDCARD]sub_path[WILDCARD]package.json imported from [WILDCARD]import_not_defined.js
|
||||
error: [ERR_PACKAGE_IMPORT_NOT_DEFINED] Package import specifier "#hi" is not defined in package [WILDCARD]sub_path[WILDCARD]package.json imported from '[WILDCARD]import_not_defined.js'
|
||||
|
|
Loading…
Reference in a new issue