summaryrefslogtreecommitdiff
path: root/ext/node/resolution.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ext/node/resolution.rs')
-rw-r--r--ext/node/resolution.rs670
1 files changed, 361 insertions, 309 deletions
diff --git a/ext/node/resolution.rs b/ext/node/resolution.rs
index 1b9a20012..5b61c1642 100644
--- a/ext/node/resolution.rs
+++ b/ext/node/resolution.rs
@@ -7,7 +7,6 @@ use std::path::PathBuf;
use deno_config::package_json::PackageJsonRc;
use deno_core::anyhow::bail;
-use deno_core::error::generic_error;
use deno_core::error::AnyError;
use deno_core::serde_json::Map;
use deno_core::serde_json::Value;
@@ -17,6 +16,33 @@ use deno_fs::FileSystemRc;
use deno_media_type::MediaType;
use crate::errors;
+use crate::errors::ClosestPkgJsonError;
+use crate::errors::ClosestPkgJsonErrorKind;
+use crate::errors::FinalizeResolutionError;
+use crate::errors::InvalidModuleSpecifierError;
+use crate::errors::InvalidPackageTargetError;
+use crate::errors::LegacyMainResolveError;
+use crate::errors::ModuleNotFoundError;
+use crate::errors::NodeResolveError;
+use crate::errors::PackageExportsResolveError;
+use crate::errors::PackageImportNotDefinedError;
+use crate::errors::PackageImportsResolveError;
+use crate::errors::PackageImportsResolveErrorKind;
+use crate::errors::PackagePathNotExportedError;
+use crate::errors::PackageResolveError;
+use crate::errors::PackageSubpathResolveError;
+use crate::errors::PackageSubpathResolveErrorKind;
+use crate::errors::PackageTargetNotFoundError;
+use crate::errors::PackageTargetResolveError;
+use crate::errors::PackageTargetResolveErrorKind;
+use crate::errors::PathToDeclarationUrlError;
+use crate::errors::ResolveBinaryCommandsError;
+use crate::errors::ResolvePkgJsonBinExportError;
+use crate::errors::ResolvePkgSubpathFromDenoModuleError;
+use crate::errors::TypeScriptNotSupportedInNpmError;
+use crate::errors::UnsupportedDirImportError;
+use crate::errors::UnsupportedEsmUrlSchemeError;
+use crate::errors::UrlToNodeResolutionError;
use crate::is_builtin_node_module;
use crate::path::to_file_specifier;
use crate::polyfill::get_module_name_from_builtin_node_module_specifier;
@@ -147,7 +173,7 @@ impl NodeResolver {
specifier: &str,
referrer: &ModuleSpecifier,
mode: NodeResolutionMode,
- ) -> Result<Option<NodeResolution>, AnyError> {
+ ) -> Result<Option<NodeResolution>, NodeResolveError> {
// Note: if we are here, then the referrer is an esm module
// TODO(bartlomieju): skipped "policy" part as we don't plan to support it
@@ -169,36 +195,29 @@ impl NodeResolver {
let protocol = url.scheme();
if protocol != "file" && protocol != "data" {
- return Err(errors::err_unsupported_esm_url_scheme(&url));
+ return Err(
+ UnsupportedEsmUrlSchemeError {
+ url_scheme: protocol.to_string(),
+ }
+ .into(),
+ );
}
// todo(dsherret): this seems wrong
if referrer.scheme() == "data" {
- let url = referrer.join(specifier).map_err(AnyError::from)?;
+ let url = referrer.join(specifier).map_err(|source| {
+ NodeResolveError::DataUrlReferrerFailed { source }
+ })?;
return Ok(Some(NodeResolution::Esm(url)));
}
}
- let url =
+ let maybe_url =
self.module_resolve(specifier, referrer, DEFAULT_CONDITIONS, mode)?;
- let url = match url {
+ let url = match maybe_url {
Some(url) => url,
None => return Ok(None),
};
- let url = match mode {
- NodeResolutionMode::Execution => url,
- NodeResolutionMode::Types => {
- let path = url.to_file_path().unwrap();
- // todo(16370): the module kind is not correct here. I think we need
- // typescript to tell us if the referrer is esm or cjs
- let maybe_decl_url =
- self.path_to_declaration_url(path, referrer, NodeModuleKind::Esm)?;
- match maybe_decl_url {
- Some(url) => url,
- None => return Ok(None),
- }
- }
- };
let resolve_response = self.url_to_node_resolution(url)?;
// TODO(bartlomieju): skipped checking errors for commonJS resolution and
@@ -212,27 +231,25 @@ impl NodeResolver {
referrer: &ModuleSpecifier,
conditions: &[&str],
mode: NodeResolutionMode,
- ) -> Result<Option<ModuleSpecifier>, AnyError> {
+ ) -> Result<Option<ModuleSpecifier>, NodeResolveError> {
// note: if we're here, the referrer is an esm module
- let url = if should_be_treated_as_relative_or_absolute_path(specifier) {
- let resolved_specifier = referrer.join(specifier)?;
- if mode.is_types() {
- let file_path = to_file_path(&resolved_specifier);
- // todo(dsherret): the node module kind is not correct and we
- // should use the value provided by typescript instead
- self.path_to_declaration_url(
- file_path,
- referrer,
- NodeModuleKind::Esm,
- )?
- } else {
- Some(resolved_specifier)
- }
+ let maybe_url = if should_be_treated_as_relative_or_absolute_path(specifier)
+ {
+ Some(referrer.join(specifier).map_err(|err| {
+ NodeResolveError::RelativeJoinError {
+ path: specifier.to_string(),
+ base: referrer.clone(),
+ source: err,
+ }
+ })?)
} else if specifier.starts_with('#') {
- let pkg_config = self.get_closest_package_json(referrer)?;
+ let pkg_config = self
+ .get_closest_package_json(referrer)
+ .map_err(PackageImportsResolveErrorKind::ClosestPkgJson)
+ .map_err(|err| PackageImportsResolveError(Box::new(err)))?;
Some(self.package_imports_resolve(
specifier,
- referrer,
+ Some(referrer),
NodeModuleKind::Esm,
pkg_config.as_deref(),
conditions,
@@ -249,8 +266,26 @@ impl NodeResolver {
mode,
)?
};
- Ok(match url {
- Some(url) => Some(self.finalize_resolution(url, referrer)?),
+
+ let Some(url) = maybe_url else {
+ return Ok(None);
+ };
+
+ let maybe_url = if mode.is_types() {
+ let file_path = to_file_path(&url);
+ // todo(16370): the referrer module kind is not correct here. I think we need
+ // typescript to tell us if the referrer is esm or cjs
+ self.path_to_declaration_url(
+ file_path,
+ Some(referrer),
+ NodeModuleKind::Esm,
+ )?
+ } else {
+ Some(url)
+ };
+
+ Ok(match maybe_url {
+ Some(url) => Some(self.finalize_resolution(url, Some(referrer))?),
None => None,
})
}
@@ -258,16 +293,21 @@ impl NodeResolver {
fn finalize_resolution(
&self,
resolved: ModuleSpecifier,
- base: &ModuleSpecifier,
- ) -> Result<ModuleSpecifier, AnyError> {
+ maybe_referrer: Option<&ModuleSpecifier>,
+ ) -> Result<ModuleSpecifier, FinalizeResolutionError> {
let encoded_sep_re = lazy_regex::regex!(r"%2F|%2C");
if encoded_sep_re.is_match(resolved.path()) {
- return Err(errors::err_invalid_module_specifier(
- resolved.path(),
- "must not include encoded \"/\" or \"\\\\\" characters",
- Some(to_file_path_string(base)),
- ));
+ return Err(
+ errors::InvalidModuleSpecifierError {
+ request: resolved.to_string(),
+ reason: Cow::Borrowed(
+ "must not include encoded \"/\" or \"\\\\\" characters",
+ ),
+ maybe_referrer: maybe_referrer.map(to_file_path_string),
+ }
+ .into(),
+ );
}
if resolved.scheme() == "node" {
@@ -295,16 +335,22 @@ impl NodeResolver {
(false, false)
};
if is_dir {
- return Err(errors::err_unsupported_dir_import(
- resolved.as_str(),
- base.as_str(),
- ));
+ return Err(
+ UnsupportedDirImportError {
+ dir_url: resolved.clone(),
+ maybe_referrer: maybe_referrer.map(ToOwned::to_owned),
+ }
+ .into(),
+ );
} else if !is_file {
- return Err(errors::err_module_not_found(
- resolved.as_str(),
- base.as_str(),
- "module",
- ));
+ return Err(
+ ModuleNotFoundError {
+ specifier: resolved,
+ maybe_referrer: maybe_referrer.map(ToOwned::to_owned),
+ typ: "module",
+ }
+ .into(),
+ );
}
Ok(resolved)
@@ -314,9 +360,9 @@ impl NodeResolver {
&self,
package_dir: &Path,
package_subpath: Option<&str>,
- referrer: &ModuleSpecifier,
+ maybe_referrer: Option<&ModuleSpecifier>,
mode: NodeResolutionMode,
- ) -> Result<Option<NodeResolution>, AnyError> {
+ ) -> Result<Option<NodeResolution>, ResolvePkgSubpathFromDenoModuleError> {
let node_module_kind = NodeModuleKind::Esm;
let package_subpath = package_subpath
.map(|s| format!("./{s}"))
@@ -324,33 +370,15 @@ impl NodeResolver {
let maybe_resolved_url = self.resolve_package_dir_subpath(
package_dir,
&package_subpath,
- referrer,
+ maybe_referrer,
node_module_kind,
DEFAULT_CONDITIONS,
mode,
)?;
let resolved_url = match maybe_resolved_url {
- Some(resolved_path) => resolved_path,
+ Some(resolved_url) => resolved_url,
None => return Ok(None),
};
- let resolved_url = match mode {
- NodeResolutionMode::Execution => resolved_url,
- NodeResolutionMode::Types => {
- if resolved_url.scheme() == "file" {
- let path = resolved_url.to_file_path().unwrap();
- match self.path_to_declaration_url(
- path,
- referrer,
- node_module_kind,
- )? {
- Some(url) => url,
- None => return Ok(None),
- }
- } else {
- resolved_url
- }
- }
- };
let resolve_response = self.url_to_node_resolution(resolved_url)?;
// TODO(bartlomieju): skipped checking errors for commonJS resolution and
// "preserveSymlinksMain"/"preserveSymlinks" options.
@@ -360,16 +388,18 @@ impl NodeResolver {
pub fn resolve_binary_commands(
&self,
package_folder: &Path,
- ) -> Result<Vec<String>, AnyError> {
- let package_json_path = package_folder.join("package.json");
- let Some(package_json) = self.load_package_json(&package_json_path)? else {
+ ) -> Result<Vec<String>, ResolveBinaryCommandsError> {
+ let pkg_json_path = package_folder.join("package.json");
+ let Some(package_json) = self.load_package_json(&pkg_json_path)? else {
return Ok(Vec::new());
};
Ok(match &package_json.bin {
Some(Value::String(_)) => {
let Some(name) = &package_json.name else {
- bail!("'{}' did not have a name", package_json_path.display());
+ return Err(ResolveBinaryCommandsError::MissingPkgJsonName {
+ pkg_json_path,
+ });
};
vec![name.to_string()]
}
@@ -384,15 +414,19 @@ impl NodeResolver {
&self,
package_folder: &Path,
sub_path: Option<&str>,
- ) -> Result<NodeResolution, AnyError> {
- let package_json_path = package_folder.join("package.json");
- let Some(package_json) = self.load_package_json(&package_json_path)? else {
- bail!(
- "Failed resolving binary export. '{}' did not exist",
- package_json_path.display(),
- )
+ ) -> Result<NodeResolution, ResolvePkgJsonBinExportError> {
+ let pkg_json_path = package_folder.join("package.json");
+ let Some(package_json) = self.load_package_json(&pkg_json_path)? else {
+ return Err(ResolvePkgJsonBinExportError::MissingPkgJson {
+ pkg_json_path,
+ });
};
- let bin_entry = resolve_bin_entry_value(&package_json, sub_path)?;
+ let bin_entry =
+ resolve_bin_entry_value(&package_json, sub_path).map_err(|err| {
+ ResolvePkgJsonBinExportError::InvalidBinProperty {
+ message: err.to_string(),
+ }
+ })?;
let url = to_file_specifier(&package_folder.join(bin_entry));
let resolve_response = self.url_to_node_resolution(url)?;
@@ -404,7 +438,7 @@ impl NodeResolver {
pub fn url_to_node_resolution(
&self,
url: ModuleSpecifier,
- ) -> Result<NodeResolution, AnyError> {
+ ) -> Result<NodeResolution, UrlToNodeResolutionError> {
let url_str = url.as_str().to_lowercase();
if url_str.starts_with("http") || url_str.ends_with(".json") {
Ok(NodeResolution::Esm(url))
@@ -419,9 +453,7 @@ impl NodeResolver {
Ok(NodeResolution::Esm(url))
} else if url_str.ends_with(".ts") || url_str.ends_with(".mts") {
if self.in_npm_package(&url) {
- Err(generic_error(format!(
- "TypeScript files are not supported in npm packages: {url}"
- )))
+ Err(TypeScriptNotSupportedInNpmError { specifier: url }.into())
} else {
Ok(NodeResolution::Esm(url))
}
@@ -434,9 +466,9 @@ impl NodeResolver {
fn path_to_declaration_url(
&self,
path: PathBuf,
- referrer: &ModuleSpecifier,
+ maybe_referrer: Option<&ModuleSpecifier>,
referrer_kind: NodeModuleKind,
- ) -> Result<Option<ModuleSpecifier>, AnyError> {
+ ) -> Result<Option<ModuleSpecifier>, PathToDeclarationUrlError> {
fn probe_extensions(
fs: &dyn deno_fs::FileSystem,
path: &Path,
@@ -497,7 +529,7 @@ impl NodeResolver {
let maybe_resolution = self.resolve_package_dir_subpath(
&path,
/* sub path */ ".",
- referrer,
+ maybe_referrer,
referrer_kind,
match referrer_kind {
NodeModuleKind::Esm => DEFAULT_CONDITIONS,
@@ -529,19 +561,22 @@ impl NodeResolver {
pub(super) fn package_imports_resolve(
&self,
name: &str,
- referrer: &ModuleSpecifier,
+ maybe_referrer: Option<&ModuleSpecifier>,
referrer_kind: NodeModuleKind,
referrer_pkg_json: Option<&PackageJson>,
conditions: &[&str],
mode: NodeResolutionMode,
- ) -> Result<ModuleSpecifier, AnyError> {
+ ) -> Result<ModuleSpecifier, PackageImportsResolveError> {
if name == "#" || name.starts_with("#/") || name.ends_with('/') {
let reason = "is not a valid internal imports specifier name";
- return Err(errors::err_invalid_module_specifier(
- name,
- reason,
- Some(to_specifier_display_string(referrer)),
- ));
+ return Err(
+ errors::InvalidModuleSpecifierError {
+ request: name.to_string(),
+ reason: Cow::Borrowed(reason),
+ maybe_referrer: maybe_referrer.map(to_specifier_display_string),
+ }
+ .into(),
+ );
}
let mut package_json_path = None;
@@ -555,7 +590,7 @@ impl NodeResolver {
target,
"",
name,
- referrer,
+ maybe_referrer,
referrer_kind,
false,
true,
@@ -596,7 +631,7 @@ impl NodeResolver {
target,
&best_match_subpath.unwrap(),
best_match,
- referrer,
+ maybe_referrer,
referrer_kind,
true,
true,
@@ -611,11 +646,14 @@ impl NodeResolver {
}
}
- Err(throw_import_not_defined(
- name,
- package_json_path.as_deref(),
- referrer,
- ))
+ Err(
+ PackageImportNotDefinedError {
+ name: name.to_string(),
+ package_json_path,
+ maybe_referrer: maybe_referrer.map(ToOwned::to_owned),
+ }
+ .into(),
+ )
}
#[allow(clippy::too_many_arguments)]
@@ -625,21 +663,24 @@ impl NodeResolver {
subpath: &str,
match_: &str,
package_json_path: &Path,
- referrer: &ModuleSpecifier,
+ maybe_referrer: Option<&ModuleSpecifier>,
referrer_kind: NodeModuleKind,
pattern: bool,
internal: bool,
conditions: &[&str],
mode: NodeResolutionMode,
- ) -> Result<ModuleSpecifier, AnyError> {
+ ) -> Result<ModuleSpecifier, PackageTargetResolveError> {
if !subpath.is_empty() && !pattern && !target.ends_with('/') {
- return Err(throw_invalid_package_target(
- match_,
- target,
- package_json_path,
- internal,
- referrer,
- ));
+ return Err(
+ InvalidPackageTargetError {
+ pkg_json_path: package_json_path.to_path_buf(),
+ sub_path: match_.to_string(),
+ target: target.to_string(),
+ is_import: internal,
+ maybe_referrer: maybe_referrer.map(ToOwned::to_owned),
+ }
+ .into(),
+ );
}
let invalid_segment_re =
lazy_regex::regex!(r"(^|\\|/)(\.\.?|node_modules)(\\|/|$)");
@@ -672,8 +713,21 @@ impl NodeResolver {
mode,
) {
Ok(Some(url)) => Ok(url),
- Ok(None) => Err(generic_error("not found")),
- Err(err) => Err(err),
+ Ok(None) => Err(
+ PackageTargetResolveErrorKind::NotFound(
+ PackageTargetNotFoundError {
+ pkg_json_path: package_json_path.to_path_buf(),
+ target: export_target.to_string(),
+ maybe_referrer: maybe_referrer.map(ToOwned::to_owned),
+ referrer_kind,
+ mode,
+ },
+ )
+ .into(),
+ ),
+ Err(err) => {
+ Err(PackageTargetResolveErrorKind::PackageResolve(err).into())
+ }
};
return match result {
@@ -692,33 +746,42 @@ impl NodeResolver {
}
}
}
- return Err(throw_invalid_package_target(
- match_,
- target,
- package_json_path,
- internal,
- referrer,
- ));
+ return Err(
+ InvalidPackageTargetError {
+ pkg_json_path: package_json_path.to_path_buf(),
+ sub_path: match_.to_string(),
+ target: target.to_string(),
+ is_import: internal,
+ maybe_referrer: maybe_referrer.map(ToOwned::to_owned),
+ }
+ .into(),
+ );
}
if invalid_segment_re.is_match(&target[2..]) {
- return Err(throw_invalid_package_target(
- match_,
- target,
- package_json_path,
- internal,
- referrer,
- ));
+ return Err(
+ InvalidPackageTargetError {
+ pkg_json_path: package_json_path.to_path_buf(),
+ sub_path: match_.to_string(),
+ target: target.to_string(),
+ is_import: internal,
+ maybe_referrer: maybe_referrer.map(ToOwned::to_owned),
+ }
+ .into(),
+ );
}
let package_path = package_json_path.parent().unwrap();
let resolved_path = package_path.join(target).clean();
if !resolved_path.starts_with(package_path) {
- return Err(throw_invalid_package_target(
- match_,
- target,
- package_json_path,
- internal,
- referrer,
- ));
+ return Err(
+ InvalidPackageTargetError {
+ pkg_json_path: package_json_path.to_path_buf(),
+ sub_path: match_.to_string(),
+ target: target.to_string(),
+ is_import: internal,
+ maybe_referrer: maybe_referrer.map(ToOwned::to_owned),
+ }
+ .into(),
+ );
}
if subpath.is_empty() {
return Ok(to_file_specifier(&resolved_path));
@@ -729,12 +792,15 @@ impl NodeResolver {
} else {
format!("{match_}{subpath}")
};
- return Err(throw_invalid_subpath(
- request,
- package_json_path,
- internal,
- referrer,
- ));
+ return Err(
+ throw_invalid_subpath(
+ request,
+ package_json_path,
+ internal,
+ maybe_referrer,
+ )
+ .into(),
+ );
}
if pattern {
let resolved_path_str = resolved_path.to_string_lossy();
@@ -752,20 +818,20 @@ impl NodeResolver {
target: &Value,
subpath: &str,
package_subpath: &str,
- referrer: &ModuleSpecifier,
+ maybe_referrer: Option<&ModuleSpecifier>,
referrer_kind: NodeModuleKind,
pattern: bool,
internal: bool,
conditions: &[&str],
mode: NodeResolutionMode,
- ) -> Result<Option<ModuleSpecifier>, AnyError> {
+ ) -> Result<Option<ModuleSpecifier>, PackageTargetResolveError> {
if let Some(target) = target.as_str() {
let url = self.resolve_package_target_string(
target,
subpath,
package_subpath,
package_json_path,
- referrer,
+ maybe_referrer,
referrer_kind,
pattern,
internal,
@@ -774,7 +840,11 @@ impl NodeResolver {
)?;
if mode.is_types() && url.scheme() == "file" {
let path = url.to_file_path().unwrap();
- return self.path_to_declaration_url(path, referrer, referrer_kind);
+ return Ok(self.path_to_declaration_url(
+ path,
+ maybe_referrer,
+ referrer_kind,
+ )?);
} else {
return Ok(Some(url));
}
@@ -790,7 +860,7 @@ impl NodeResolver {
target_item,
subpath,
package_subpath,
- referrer,
+ maybe_referrer,
referrer_kind,
pattern,
internal,
@@ -804,14 +874,15 @@ impl NodeResolver {
last_error = None;
continue;
}
- Err(e) => {
- let err_string = e.to_string();
- last_error = Some(e);
- if err_string.starts_with("[ERR_INVALID_PACKAGE_TARGET]") {
+ Err(e) => match e.as_kind() {
+ PackageTargetResolveErrorKind::InvalidPackageTarget(_) => {
+ last_error = Some(e);
continue;
}
- return Err(last_error.unwrap());
- }
+ _ => {
+ return Err(e);
+ }
+ },
}
}
if last_error.is_none() {
@@ -838,7 +909,7 @@ impl NodeResolver {
condition_target,
subpath,
package_subpath,
- referrer,
+ maybe_referrer,
referrer_kind,
pattern,
internal,
@@ -857,13 +928,16 @@ impl NodeResolver {
return Ok(None);
}
- Err(throw_invalid_package_target(
- package_subpath,
- &target.to_string(),
- package_json_path,
- internal,
- referrer,
- ))
+ Err(
+ InvalidPackageTargetError {
+ pkg_json_path: package_json_path.to_path_buf(),
+ sub_path: package_subpath.to_string(),
+ target: target.to_string(),
+ is_import: internal,
+ maybe_referrer: maybe_referrer.map(ToOwned::to_owned),
+ }
+ .into(),
+ )
}
#[allow(clippy::too_many_arguments)]
@@ -872,11 +946,11 @@ impl NodeResolver {
package_json_path: &Path,
package_subpath: &str,
package_exports: &Map<String, Value>,
- referrer: &ModuleSpecifier,
+ maybe_referrer: Option<&ModuleSpecifier>,
referrer_kind: NodeModuleKind,
conditions: &[&str],
mode: NodeResolutionMode,
- ) -> Result<ModuleSpecifier, AnyError> {
+ ) -> Result<ModuleSpecifier, PackageExportsResolveError> {
if package_exports.contains_key(package_subpath)
&& package_subpath.find('*').is_none()
&& !package_subpath.ends_with('/')
@@ -887,7 +961,7 @@ impl NodeResolver {
target,
"",
package_subpath,
- referrer,
+ maybe_referrer,
referrer_kind,
false,
false,
@@ -896,12 +970,15 @@ impl NodeResolver {
)?;
return match resolved {
Some(resolved) => Ok(resolved),
- None => Err(throw_exports_not_found(
- package_subpath,
- package_json_path,
- referrer,
- mode,
- )),
+ None => Err(
+ PackagePathNotExportedError {
+ pkg_json_path: package_json_path.to_path_buf(),
+ subpath: package_subpath.to_string(),
+ maybe_referrer: maybe_referrer.map(ToOwned::to_owned),
+ mode,
+ }
+ .into(),
+ ),
};
}
@@ -946,7 +1023,7 @@ impl NodeResolver {
target,
&best_match_subpath.unwrap(),
best_match,
- referrer,
+ maybe_referrer,
referrer_kind,
true,
false,
@@ -956,21 +1033,27 @@ impl NodeResolver {
if let Some(resolved) = maybe_resolved {
return Ok(resolved);
} else {
- return Err(throw_exports_not_found(
- package_subpath,
- package_json_path,
- referrer,
- mode,
- ));
+ return Err(
+ PackagePathNotExportedError {
+ pkg_json_path: package_json_path.to_path_buf(),
+ subpath: package_subpath.to_string(),
+ maybe_referrer: maybe_referrer.map(ToOwned::to_owned),
+ mode,
+ }
+ .into(),
+ );
}
}
- Err(throw_exports_not_found(
- package_subpath,
- package_json_path,
- referrer,
- mode,
- ))
+ Err(
+ PackagePathNotExportedError {
+ pkg_json_path: package_json_path.to_path_buf(),
+ subpath: package_subpath.to_string(),
+ maybe_referrer: maybe_referrer.map(ToOwned::to_owned),
+ mode,
+ }
+ .into(),
+ )
}
pub(super) fn package_resolve(
@@ -980,7 +1063,7 @@ impl NodeResolver {
referrer_kind: NodeModuleKind,
conditions: &[&str],
mode: NodeResolutionMode,
- ) -> Result<Option<ModuleSpecifier>, AnyError> {
+ ) -> Result<Option<ModuleSpecifier>, PackageResolveError> {
let (package_name, package_subpath, _is_scoped) =
parse_npm_pkg_name(specifier, referrer)?;
@@ -995,23 +1078,26 @@ impl NodeResolver {
&package_config.path,
&package_subpath,
exports,
- referrer,
+ Some(referrer),
referrer_kind,
conditions,
mode,
)
- .map(Some);
+ .map(Some)
+ .map_err(|err| err.into());
}
}
- self.resolve_package_subpath_for_package(
- &package_name,
- &package_subpath,
- referrer,
- referrer_kind,
- conditions,
- mode,
- )
+ self
+ .resolve_package_subpath_for_package(
+ &package_name,
+ &package_subpath,
+ referrer,
+ referrer_kind,
+ conditions,
+ mode,
+ )
+ .map_err(|err| err.into())
}
#[allow(clippy::too_many_arguments)]
@@ -1023,7 +1109,7 @@ impl NodeResolver {
referrer_kind: NodeModuleKind,
conditions: &[&str],
mode: NodeResolutionMode,
- ) -> Result<Option<ModuleSpecifier>, AnyError> {
+ ) -> Result<Option<ModuleSpecifier>, PackageSubpathResolveError> {
let result = self.resolve_package_subpath_for_package_inner(
package_name,
package_subpath,
@@ -1058,7 +1144,7 @@ impl NodeResolver {
referrer_kind: NodeModuleKind,
conditions: &[&str],
mode: NodeResolutionMode,
- ) -> Result<Option<ModuleSpecifier>, AnyError> {
+ ) -> Result<Option<ModuleSpecifier>, PackageSubpathResolveError> {
let package_dir_path = self
.npm_resolver
.resolve_package_folder_from_package(package_name, referrer)?;
@@ -1080,7 +1166,7 @@ impl NodeResolver {
self.resolve_package_dir_subpath(
&package_dir_path,
package_subpath,
- referrer,
+ Some(referrer),
referrer_kind,
conditions,
mode,
@@ -1092,28 +1178,30 @@ impl NodeResolver {
&self,
package_dir_path: &Path,
package_subpath: &str,
- referrer: &ModuleSpecifier,
+ maybe_referrer: Option<&ModuleSpecifier>,
referrer_kind: NodeModuleKind,
conditions: &[&str],
mode: NodeResolutionMode,
- ) -> Result<Option<ModuleSpecifier>, AnyError> {
+ ) -> Result<Option<ModuleSpecifier>, PackageSubpathResolveError> {
let package_json_path = package_dir_path.join("package.json");
match self.load_package_json(&package_json_path)? {
Some(pkg_json) => self.resolve_package_subpath(
&pkg_json,
package_subpath,
- referrer,
+ maybe_referrer,
referrer_kind,
conditions,
mode,
),
- None => self.resolve_package_subpath_no_pkg_json(
- package_dir_path,
- package_subpath,
- referrer,
- referrer_kind,
- mode,
- ),
+ None => self
+ .resolve_package_subpath_no_pkg_json(
+ package_dir_path,
+ package_subpath,
+ maybe_referrer,
+ referrer_kind,
+ mode,
+ )
+ .map_err(|err| PackageSubpathResolveErrorKind::LegacyExact(err).into()),
}
}
@@ -1122,11 +1210,11 @@ impl NodeResolver {
&self,
package_json: &PackageJson,
package_subpath: &str,
- referrer: &ModuleSpecifier,
+ referrer: Option<&ModuleSpecifier>,
referrer_kind: NodeModuleKind,
conditions: &[&str],
mode: NodeResolutionMode,
- ) -> Result<Option<ModuleSpecifier>, AnyError> {
+ ) -> Result<Option<ModuleSpecifier>, PackageSubpathResolveError> {
if let Some(exports) = &package_json.exports {
let result = self.package_exports_resolve(
&package_json.path,
@@ -1141,48 +1229,48 @@ impl NodeResolver {
Ok(found) => return Ok(Some(found)),
Err(exports_err) => {
if mode.is_types() && package_subpath == "." {
- return self.legacy_main_resolve(
- package_json,
- referrer,
- referrer_kind,
- mode,
- );
+ return self
+ .legacy_main_resolve(package_json, referrer, referrer_kind, mode)
+ .map_err(|err| {
+ PackageSubpathResolveErrorKind::LegacyMain(err).into()
+ });
}
- return Err(exports_err);
+ return Err(
+ PackageSubpathResolveErrorKind::Exports(exports_err).into(),
+ );
}
}
}
if package_subpath == "." {
- return self.legacy_main_resolve(
- package_json,
+ return self
+ .legacy_main_resolve(package_json, referrer, referrer_kind, mode)
+ .map_err(|err| PackageSubpathResolveErrorKind::LegacyMain(err).into());
+ }
+
+ self
+ .resolve_subpath_exact(
+ package_json.path.parent().unwrap(),
+ package_subpath,
referrer,
referrer_kind,
mode,
- );
- }
-
- self.resolve_subpath_exact(
- package_json.path.parent().unwrap(),
- package_subpath,
- referrer,
- referrer_kind,
- mode,
- )
+ )
+ .map_err(|err| PackageSubpathResolveErrorKind::LegacyExact(err).into())
}
fn resolve_subpath_exact(
&self,
directory: &Path,
package_subpath: &str,
- referrer: &ModuleSpecifier,
+ referrer: Option<&ModuleSpecifier>,
referrer_kind: NodeModuleKind,
mode: NodeResolutionMode,
- ) -> Result<Option<ModuleSpecifier>, AnyError> {
+ ) -> Result<Option<ModuleSpecifier>, PathToDeclarationUrlError> {
assert_ne!(package_subpath, ".");
let file_path = directory.join(package_subpath);
if mode.is_types() {
- self.path_to_declaration_url(file_path, referrer, referrer_kind)
+ Ok(self.path_to_declaration_url(file_path, referrer, referrer_kind)?)
} else {
Ok(Some(to_file_specifier(&file_path)))
}
@@ -1192,12 +1280,12 @@ impl NodeResolver {
&self,
directory: &Path,
package_subpath: &str,
- referrer: &ModuleSpecifier,
+ referrer: Option<&ModuleSpecifier>,
referrer_kind: NodeModuleKind,
mode: NodeResolutionMode,
- ) -> Result<Option<ModuleSpecifier>, AnyError> {
+ ) -> Result<Option<ModuleSpecifier>, PathToDeclarationUrlError> {
if package_subpath == "." {
- self.legacy_index_resolve(directory, referrer_kind, mode)
+ Ok(self.legacy_index_resolve(directory, referrer_kind, mode))
} else {
self.resolve_subpath_exact(
directory,
@@ -1212,7 +1300,7 @@ impl NodeResolver {
pub fn get_closest_package_json(
&self,
url: &ModuleSpecifier,
- ) -> Result<Option<PackageJsonRc>, AnyError> {
+ ) -> Result<Option<PackageJsonRc>, ClosestPkgJsonError> {
let Ok(file_path) = url.to_file_path() else {
return Ok(None);
};
@@ -1222,10 +1310,15 @@ impl NodeResolver {
pub fn get_closest_package_json_from_path(
&self,
file_path: &Path,
- ) -> Result<Option<PackageJsonRc>, AnyError> {
- let current_dir = deno_core::strip_unc_prefix(
- self.fs.realpath_sync(file_path.parent().unwrap())?,
- );
+ ) -> Result<Option<PackageJsonRc>, ClosestPkgJsonError> {
+ let parent_dir = file_path.parent().unwrap();
+ let current_dir =
+ deno_core::strip_unc_prefix(self.fs.realpath_sync(parent_dir).map_err(
+ |source| ClosestPkgJsonErrorKind::CanonicalizingDir {
+ dir_path: parent_dir.to_path_buf(),
+ source: source.into_io_error(),
+ },
+ )?);
let mut current_dir = current_dir.as_path();
let package_json_path = current_dir.join("package.json");
if let Some(pkg_json) = self.load_package_json(&package_json_path)? {
@@ -1255,10 +1348,10 @@ impl NodeResolver {
pub(super) fn legacy_main_resolve(
&self,
package_json: &PackageJson,
- referrer: &ModuleSpecifier,
+ maybe_referrer: Option<&ModuleSpecifier>,
referrer_kind: NodeModuleKind,
mode: NodeResolutionMode,
- ) -> Result<Option<ModuleSpecifier>, AnyError> {
+ ) -> Result<Option<ModuleSpecifier>, LegacyMainResolveError> {
let maybe_main = if mode.is_types() {
match package_json.types.as_ref() {
Some(types) => Some(types.as_str()),
@@ -1267,8 +1360,9 @@ impl NodeResolver {
// a corresponding declaration file
if let Some(main) = package_json.main(referrer_kind) {
let main = package_json.path.parent().unwrap().join(main).clean();
- let maybe_decl_url =
- self.path_to_declaration_url(main, referrer, referrer_kind)?;
+ let maybe_decl_url = self
+ .path_to_declaration_url(main, maybe_referrer, referrer_kind)
+ .map_err(LegacyMainResolveError::PathToDeclarationUrl)?;
if let Some(path) = maybe_decl_url {
return Ok(Some(path));
}
@@ -1318,11 +1412,11 @@ impl NodeResolver {
}
}
- self.legacy_index_resolve(
+ Ok(self.legacy_index_resolve(
package_json.path.parent().unwrap(),
referrer_kind,
mode,
- )
+ ))
}
fn legacy_index_resolve(
@@ -1330,7 +1424,7 @@ impl NodeResolver {
directory: &Path,
referrer_kind: NodeModuleKind,
mode: NodeResolutionMode,
- ) -> Result<Option<ModuleSpecifier>, AnyError> {
+ ) -> Option<ModuleSpecifier> {
let index_file_names = if mode.is_types() {
// todo(dsherret): investigate exactly how typescript does this
match referrer_kind {
@@ -1344,11 +1438,11 @@ impl NodeResolver {
let guess = directory.join(index_file_name).clean();
if self.fs.is_file_sync(&guess) {
// TODO(bartlomieju): emitLegacyIndexDeprecation()
- return Ok(Some(to_file_specifier(&guess)));
+ return Some(to_file_specifier(&guess));
}
}
- Ok(None)
+ None
}
}
@@ -1524,71 +1618,29 @@ fn to_specifier_display_string(url: &ModuleSpecifier) -> String {
}
}
-fn throw_import_not_defined(
- specifier: &str,
- package_json_path: Option<&Path>,
- base: &ModuleSpecifier,
-) -> AnyError {
- errors::err_package_import_not_defined(
- specifier,
- package_json_path.map(|p| p.parent().unwrap().display().to_string()),
- &to_specifier_display_string(base),
- )
-}
-
-fn throw_invalid_package_target(
- subpath: &str,
- target: &str,
- package_json_path: &Path,
- internal: bool,
- referrer: &ModuleSpecifier,
-) -> AnyError {
- errors::err_invalid_package_target(
- &package_json_path.parent().unwrap().display().to_string(),
- subpath,
- target,
- internal,
- Some(referrer.to_string()),
- )
-}
-
fn throw_invalid_subpath(
subpath: String,
package_json_path: &Path,
internal: bool,
- referrer: &ModuleSpecifier,
-) -> AnyError {
+ maybe_referrer: Option<&ModuleSpecifier>,
+) -> InvalidModuleSpecifierError {
let ie = if internal { "imports" } else { "exports" };
let reason = format!(
"request is not a valid subpath for the \"{}\" resolution of {}",
ie,
package_json_path.display(),
);
- errors::err_invalid_module_specifier(
- &subpath,
- &reason,
- Some(to_specifier_display_string(referrer)),
- )
-}
-
-fn throw_exports_not_found(
- subpath: &str,
- package_json_path: &Path,
- referrer: &ModuleSpecifier,
- mode: NodeResolutionMode,
-) -> AnyError {
- errors::err_package_path_not_exported(
- package_json_path.parent().unwrap().display().to_string(),
- subpath,
- Some(to_specifier_display_string(referrer)),
- mode,
- )
+ InvalidModuleSpecifierError {
+ request: subpath,
+ reason: Cow::Owned(reason),
+ maybe_referrer: maybe_referrer.map(to_specifier_display_string),
+ }
}
pub fn parse_npm_pkg_name(
specifier: &str,
referrer: &ModuleSpecifier,
-) -> Result<(String, String, bool), AnyError> {
+) -> Result<(String, String, bool), InvalidModuleSpecifierError> {
let mut separator_index = specifier.find('/');
let mut valid_package_name = true;
let mut is_scoped = false;
@@ -1620,11 +1672,11 @@ pub fn parse_npm_pkg_name(
}
if !valid_package_name {
- return Err(errors::err_invalid_module_specifier(
- specifier,
- "is not a valid package name",
- Some(to_specifier_display_string(referrer)),
- ));
+ return Err(errors::InvalidModuleSpecifierError {
+ request: specifier.to_string(),
+ reason: Cow::Borrowed("is not a valid package name"),
+ maybe_referrer: Some(to_specifier_display_string(referrer)),
+ });
}
let package_subpath = if let Some(index) = separator_index {