mirror of
https://github.com/denoland/deno.git
synced 2024-11-25 15:29:32 -05:00
refactor(node): combine node resolution code for resolving a package subpath from external code (#20791)
We had two methods that did the same functionality.
This commit is contained in:
parent
64f9155126
commit
1ff525e25b
7 changed files with 119 additions and 126 deletions
|
@ -1,7 +1,5 @@
|
||||||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
@ -13,6 +11,7 @@ use deno_runtime::deno_node::PackageJson;
|
||||||
use deno_semver::package::PackageReq;
|
use deno_semver::package::PackageReq;
|
||||||
use deno_semver::VersionReq;
|
use deno_semver::VersionReq;
|
||||||
use deno_semver::VersionReqSpecifierParseError;
|
use deno_semver::VersionReqSpecifierParseError;
|
||||||
|
use indexmap::IndexMap;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Debug, Error, Clone)]
|
#[derive(Debug, Error, Clone)]
|
||||||
|
@ -26,7 +25,7 @@ pub enum PackageJsonDepValueParseError {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type PackageJsonDeps =
|
pub type PackageJsonDeps =
|
||||||
BTreeMap<String, Result<PackageReq, PackageJsonDepValueParseError>>;
|
IndexMap<String, Result<PackageReq, PackageJsonDepValueParseError>>;
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct PackageJsonDepsProvider(Option<PackageJsonDeps>);
|
pub struct PackageJsonDepsProvider(Option<PackageJsonDeps>);
|
||||||
|
@ -92,24 +91,25 @@ pub fn get_local_package_json_version_reqs(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_deps(
|
fn insert_deps(
|
||||||
deps: Option<&HashMap<String, String>>,
|
deps: Option<&IndexMap<String, String>>,
|
||||||
result: &mut PackageJsonDeps,
|
result: &mut PackageJsonDeps,
|
||||||
) {
|
) {
|
||||||
if let Some(deps) = deps {
|
if let Some(deps) = deps {
|
||||||
for (key, value) in deps {
|
for (key, value) in deps {
|
||||||
result.insert(key.to_string(), parse_entry(key, value));
|
result
|
||||||
|
.entry(key.to_string())
|
||||||
|
.or_insert_with(|| parse_entry(key, value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let deps = package_json.dependencies.as_ref();
|
let deps = package_json.dependencies.as_ref();
|
||||||
let dev_deps = package_json.dev_dependencies.as_ref();
|
let dev_deps = package_json.dev_dependencies.as_ref();
|
||||||
let mut result = BTreeMap::new();
|
let mut result = IndexMap::new();
|
||||||
|
|
||||||
// insert the dev dependencies first so the dependencies will
|
// favors the deps over dev_deps
|
||||||
// take priority and overwrite any collisions
|
|
||||||
insert_deps(dev_deps, &mut result);
|
|
||||||
insert_deps(deps, &mut result);
|
insert_deps(deps, &mut result);
|
||||||
|
insert_deps(dev_deps, &mut result);
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
@ -182,7 +182,7 @@ mod test {
|
||||||
|
|
||||||
fn get_local_package_json_version_reqs_for_tests(
|
fn get_local_package_json_version_reqs_for_tests(
|
||||||
package_json: &PackageJson,
|
package_json: &PackageJson,
|
||||||
) -> BTreeMap<String, Result<PackageReq, String>> {
|
) -> IndexMap<String, Result<PackageReq, String>> {
|
||||||
get_local_package_json_version_reqs(package_json)
|
get_local_package_json_version_reqs(package_json)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(k, v)| {
|
.map(|(k, v)| {
|
||||||
|
@ -194,17 +194,17 @@ mod test {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect::<BTreeMap<_, _>>()
|
.collect::<IndexMap<_, _>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_local_package_json_version_reqs() {
|
fn test_get_local_package_json_version_reqs() {
|
||||||
let mut package_json = PackageJson::empty(PathBuf::from("/package.json"));
|
let mut package_json = PackageJson::empty(PathBuf::from("/package.json"));
|
||||||
package_json.dependencies = Some(HashMap::from([
|
package_json.dependencies = Some(IndexMap::from([
|
||||||
("test".to_string(), "^1.2".to_string()),
|
("test".to_string(), "^1.2".to_string()),
|
||||||
("other".to_string(), "npm:package@~1.3".to_string()),
|
("other".to_string(), "npm:package@~1.3".to_string()),
|
||||||
]));
|
]));
|
||||||
package_json.dev_dependencies = Some(HashMap::from([
|
package_json.dev_dependencies = Some(IndexMap::from([
|
||||||
("package_b".to_string(), "~2.2".to_string()),
|
("package_b".to_string(), "~2.2".to_string()),
|
||||||
// should be ignored
|
// should be ignored
|
||||||
("other".to_string(), "^3.2".to_string()),
|
("other".to_string(), "^3.2".to_string()),
|
||||||
|
@ -212,7 +212,7 @@ mod test {
|
||||||
let deps = get_local_package_json_version_reqs_for_tests(&package_json);
|
let deps = get_local_package_json_version_reqs_for_tests(&package_json);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
deps,
|
deps,
|
||||||
BTreeMap::from([
|
IndexMap::from([
|
||||||
(
|
(
|
||||||
"test".to_string(),
|
"test".to_string(),
|
||||||
Ok(PackageReq::from_str("test@^1.2").unwrap())
|
Ok(PackageReq::from_str("test@^1.2").unwrap())
|
||||||
|
@ -232,14 +232,14 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_local_package_json_version_reqs_errors_non_npm_specifier() {
|
fn test_get_local_package_json_version_reqs_errors_non_npm_specifier() {
|
||||||
let mut package_json = PackageJson::empty(PathBuf::from("/package.json"));
|
let mut package_json = PackageJson::empty(PathBuf::from("/package.json"));
|
||||||
package_json.dependencies = Some(HashMap::from([(
|
package_json.dependencies = Some(IndexMap::from([(
|
||||||
"test".to_string(),
|
"test".to_string(),
|
||||||
"1.x - 1.3".to_string(),
|
"1.x - 1.3".to_string(),
|
||||||
)]));
|
)]));
|
||||||
let map = get_local_package_json_version_reqs_for_tests(&package_json);
|
let map = get_local_package_json_version_reqs_for_tests(&package_json);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
map,
|
map,
|
||||||
BTreeMap::from([(
|
IndexMap::from([(
|
||||||
"test".to_string(),
|
"test".to_string(),
|
||||||
Err(
|
Err(
|
||||||
concat!(
|
concat!(
|
||||||
|
@ -256,7 +256,7 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_local_package_json_version_reqs_skips_certain_specifiers() {
|
fn test_get_local_package_json_version_reqs_skips_certain_specifiers() {
|
||||||
let mut package_json = PackageJson::empty(PathBuf::from("/package.json"));
|
let mut package_json = PackageJson::empty(PathBuf::from("/package.json"));
|
||||||
package_json.dependencies = Some(HashMap::from([
|
package_json.dependencies = Some(IndexMap::from([
|
||||||
("test".to_string(), "1".to_string()),
|
("test".to_string(), "1".to_string()),
|
||||||
("work-test".to_string(), "workspace:1.1.1".to_string()),
|
("work-test".to_string(), "workspace:1.1.1".to_string()),
|
||||||
("file-test".to_string(), "file:something".to_string()),
|
("file-test".to_string(), "file:something".to_string()),
|
||||||
|
@ -267,7 +267,7 @@ mod test {
|
||||||
let result = get_local_package_json_version_reqs_for_tests(&package_json);
|
let result = get_local_package_json_version_reqs_for_tests(&package_json);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result,
|
result,
|
||||||
BTreeMap::from([
|
IndexMap::from([
|
||||||
(
|
(
|
||||||
"file-test".to_string(),
|
"file-test".to_string(),
|
||||||
Err("Not implemented scheme 'file'".to_string()),
|
Err("Not implemented scheme 'file'".to_string()),
|
||||||
|
|
|
@ -47,7 +47,6 @@ use indexmap::IndexMap;
|
||||||
use lsp::Url;
|
use lsp::Url;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use package_json::PackageJsonDepsProvider;
|
use package_json::PackageJsonDepsProvider;
|
||||||
use std::collections::BTreeMap;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
@ -1267,8 +1266,8 @@ impl Documents {
|
||||||
if let Some(package_json_deps) = &maybe_package_json_deps {
|
if let Some(package_json_deps) = &maybe_package_json_deps {
|
||||||
// We need to ensure the hashing is deterministic so explicitly type
|
// We need to ensure the hashing is deterministic so explicitly type
|
||||||
// this in order to catch if the type of package_json_deps ever changes
|
// this in order to catch if the type of package_json_deps ever changes
|
||||||
// from a sorted/deterministic BTreeMap to something else.
|
// from a sorted/deterministic IndexMap to something else.
|
||||||
let package_json_deps: &BTreeMap<_, _> = *package_json_deps;
|
let package_json_deps: &IndexMap<_, _> = *package_json_deps;
|
||||||
for (key, value) in package_json_deps {
|
for (key, value) in package_json_deps {
|
||||||
hasher.write_hashable(key);
|
hasher.write_hashable(key);
|
||||||
match value {
|
match value {
|
||||||
|
|
|
@ -216,7 +216,7 @@ impl<TCjsCodeAnalyzer: CjsCodeAnalyzer> NodeCodeTranslator<TCjsCodeAnalyzer> {
|
||||||
if let Some(exports) = &package_json.exports {
|
if let Some(exports) = &package_json.exports {
|
||||||
return self.node_resolver.package_exports_resolve(
|
return self.node_resolver.package_exports_resolve(
|
||||||
&package_json_path,
|
&package_json_path,
|
||||||
package_subpath,
|
&package_subpath,
|
||||||
exports,
|
exports,
|
||||||
referrer,
|
referrer,
|
||||||
NodeModuleKind::Esm,
|
NodeModuleKind::Esm,
|
||||||
|
|
|
@ -53,8 +53,8 @@ pub fn err_module_not_found(path: &str, base: &str, typ: &str) -> AnyError {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn err_invalid_package_target(
|
pub fn err_invalid_package_target(
|
||||||
pkg_path: String,
|
pkg_path: &str,
|
||||||
key: String,
|
key: &str,
|
||||||
target: String,
|
target: String,
|
||||||
is_import: bool,
|
is_import: bool,
|
||||||
maybe_referrer: Option<String>,
|
maybe_referrer: Option<String>,
|
||||||
|
@ -95,7 +95,7 @@ pub fn err_invalid_package_target(
|
||||||
|
|
||||||
pub fn err_package_path_not_exported(
|
pub fn err_package_path_not_exported(
|
||||||
mut pkg_path: String,
|
mut pkg_path: String,
|
||||||
subpath: String,
|
subpath: &str,
|
||||||
maybe_referrer: Option<String>,
|
maybe_referrer: Option<String>,
|
||||||
mode: NodeResolutionMode,
|
mode: NodeResolutionMode,
|
||||||
) -> AnyError {
|
) -> AnyError {
|
||||||
|
@ -178,7 +178,7 @@ mod test {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
err_package_path_not_exported(
|
err_package_path_not_exported(
|
||||||
"test_path".to_string(),
|
"test_path".to_string(),
|
||||||
"./jsx-runtime".to_string(),
|
"./jsx-runtime",
|
||||||
None,
|
None,
|
||||||
NodeResolutionMode::Types,
|
NodeResolutionMode::Types,
|
||||||
)
|
)
|
||||||
|
@ -188,7 +188,7 @@ mod test {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
err_package_path_not_exported(
|
err_package_path_not_exported(
|
||||||
"test_path".to_string(),
|
"test_path".to_string(),
|
||||||
".".to_string(),
|
".",
|
||||||
None,
|
None,
|
||||||
NodeResolutionMode::Types,
|
NodeResolutionMode::Types,
|
||||||
)
|
)
|
||||||
|
|
|
@ -423,7 +423,7 @@ where
|
||||||
node_resolver
|
node_resolver
|
||||||
.package_exports_resolve(
|
.package_exports_resolve(
|
||||||
&pkg.path,
|
&pkg.path,
|
||||||
expansion,
|
&expansion,
|
||||||
exports,
|
exports,
|
||||||
&referrer,
|
&referrer,
|
||||||
NodeModuleKind::Cjs,
|
NodeModuleKind::Cjs,
|
||||||
|
@ -507,7 +507,7 @@ where
|
||||||
node_resolver
|
node_resolver
|
||||||
.package_exports_resolve(
|
.package_exports_resolve(
|
||||||
&pkg.path,
|
&pkg.path,
|
||||||
format!(".{expansion}"),
|
&format!(".{expansion}"),
|
||||||
exports,
|
exports,
|
||||||
&referrer,
|
&referrer,
|
||||||
NodeModuleKind::Cjs,
|
NodeModuleKind::Cjs,
|
||||||
|
|
|
@ -36,8 +36,8 @@ pub struct PackageJson {
|
||||||
pub path: PathBuf,
|
pub path: PathBuf,
|
||||||
pub typ: String,
|
pub typ: String,
|
||||||
pub types: Option<String>,
|
pub types: Option<String>,
|
||||||
pub dependencies: Option<HashMap<String, String>>,
|
pub dependencies: Option<IndexMap<String, String>>,
|
||||||
pub dev_dependencies: Option<HashMap<String, String>>,
|
pub dev_dependencies: Option<IndexMap<String, String>>,
|
||||||
pub scripts: Option<IndexMap<String, String>>,
|
pub scripts: Option<IndexMap<String, String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ impl PackageJson {
|
||||||
|
|
||||||
let dependencies = package_json.get("dependencies").and_then(|d| {
|
let dependencies = package_json.get("dependencies").and_then(|d| {
|
||||||
if d.is_object() {
|
if d.is_object() {
|
||||||
let deps: HashMap<String, String> =
|
let deps: IndexMap<String, String> =
|
||||||
serde_json::from_value(d.to_owned()).unwrap();
|
serde_json::from_value(d.to_owned()).unwrap();
|
||||||
Some(deps)
|
Some(deps)
|
||||||
} else {
|
} else {
|
||||||
|
@ -155,7 +155,7 @@ impl PackageJson {
|
||||||
});
|
});
|
||||||
let dev_dependencies = package_json.get("devDependencies").and_then(|d| {
|
let dev_dependencies = package_json.get("devDependencies").and_then(|d| {
|
||||||
if d.is_object() {
|
if d.is_object() {
|
||||||
let deps: HashMap<String, String> =
|
let deps: IndexMap<String, String> =
|
||||||
serde_json::from_value(d.to_owned()).unwrap();
|
serde_json::from_value(d.to_owned()).unwrap();
|
||||||
Some(deps)
|
Some(deps)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -327,18 +327,24 @@ impl NodeResolver {
|
||||||
|
|
||||||
pub fn resolve_npm_reference(
|
pub fn resolve_npm_reference(
|
||||||
&self,
|
&self,
|
||||||
package_folder: &Path,
|
package_dir: &Path,
|
||||||
sub_path: Option<&str>,
|
package_subpath: Option<&str>,
|
||||||
mode: NodeResolutionMode,
|
mode: NodeResolutionMode,
|
||||||
permissions: &dyn NodePermissions,
|
permissions: &dyn NodePermissions,
|
||||||
) -> Result<Option<NodeResolution>, AnyError> {
|
) -> Result<Option<NodeResolution>, AnyError> {
|
||||||
|
let package_json_path = package_dir.join("package.json");
|
||||||
|
let referrer = ModuleSpecifier::from_directory_path(package_dir).unwrap();
|
||||||
|
let package_json =
|
||||||
|
self.load_package_json(permissions, package_json_path.clone())?;
|
||||||
let node_module_kind = NodeModuleKind::Esm;
|
let node_module_kind = NodeModuleKind::Esm;
|
||||||
let maybe_resolved_path = self
|
let package_subpath = package_subpath
|
||||||
.package_config_resolve(
|
|
||||||
&sub_path
|
|
||||||
.map(|s| format!("./{s}"))
|
.map(|s| format!("./{s}"))
|
||||||
.unwrap_or_else(|| ".".to_string()),
|
.unwrap_or_else(|| ".".to_string());
|
||||||
package_folder,
|
let maybe_resolved_path = self
|
||||||
|
.resolve_package_subpath(
|
||||||
|
&package_json,
|
||||||
|
&package_subpath,
|
||||||
|
&referrer,
|
||||||
node_module_kind,
|
node_module_kind,
|
||||||
DEFAULT_CONDITIONS,
|
DEFAULT_CONDITIONS,
|
||||||
mode,
|
mode,
|
||||||
|
@ -346,8 +352,9 @@ impl NodeResolver {
|
||||||
)
|
)
|
||||||
.with_context(|| {
|
.with_context(|| {
|
||||||
format!(
|
format!(
|
||||||
"Failed resolving package config for '{}'",
|
"Failed resolving package subpath '{}' for '{}'",
|
||||||
package_folder.join("package.json").display()
|
package_subpath,
|
||||||
|
package_json.path.display()
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
let resolved_path = match maybe_resolved_path {
|
let resolved_path = match maybe_resolved_path {
|
||||||
|
@ -440,53 +447,6 @@ impl NodeResolver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn package_config_resolve(
|
|
||||||
&self,
|
|
||||||
package_subpath: &str,
|
|
||||||
package_dir: &Path,
|
|
||||||
referrer_kind: NodeModuleKind,
|
|
||||||
conditions: &[&str],
|
|
||||||
mode: NodeResolutionMode,
|
|
||||||
permissions: &dyn NodePermissions,
|
|
||||||
) -> Result<Option<PathBuf>, AnyError> {
|
|
||||||
let package_json_path = package_dir.join("package.json");
|
|
||||||
let referrer = ModuleSpecifier::from_directory_path(package_dir).unwrap();
|
|
||||||
let package_config =
|
|
||||||
self.load_package_json(permissions, package_json_path.clone())?;
|
|
||||||
if let Some(exports) = &package_config.exports {
|
|
||||||
let result = self.package_exports_resolve(
|
|
||||||
&package_json_path,
|
|
||||||
package_subpath.to_string(),
|
|
||||||
exports,
|
|
||||||
&referrer,
|
|
||||||
referrer_kind,
|
|
||||||
conditions,
|
|
||||||
mode,
|
|
||||||
permissions,
|
|
||||||
);
|
|
||||||
match result {
|
|
||||||
Ok(found) => return Ok(Some(found)),
|
|
||||||
Err(exports_err) => {
|
|
||||||
if mode.is_types() && package_subpath == "." {
|
|
||||||
if let Ok(Some(path)) =
|
|
||||||
self.legacy_main_resolve(&package_config, referrer_kind, mode)
|
|
||||||
{
|
|
||||||
return Ok(Some(path));
|
|
||||||
} else {
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Err(exports_err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if package_subpath == "." {
|
|
||||||
return self.legacy_main_resolve(&package_config, referrer_kind, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Some(package_dir.join(package_subpath)))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks if the resolved file has a corresponding declaration file.
|
/// Checks if the resolved file has a corresponding declaration file.
|
||||||
pub(super) fn path_to_declaration_path(
|
pub(super) fn path_to_declaration_path(
|
||||||
&self,
|
&self,
|
||||||
|
@ -592,8 +552,8 @@ impl NodeResolver {
|
||||||
let maybe_resolved = self.resolve_package_target(
|
let maybe_resolved = self.resolve_package_target(
|
||||||
package_json_path.as_ref().unwrap(),
|
package_json_path.as_ref().unwrap(),
|
||||||
imports.get(name).unwrap().to_owned(),
|
imports.get(name).unwrap().to_owned(),
|
||||||
"".to_string(),
|
"",
|
||||||
name.to_string(),
|
name,
|
||||||
referrer,
|
referrer,
|
||||||
referrer_kind,
|
referrer_kind,
|
||||||
false,
|
false,
|
||||||
|
@ -635,8 +595,8 @@ impl NodeResolver {
|
||||||
let maybe_resolved = self.resolve_package_target(
|
let maybe_resolved = self.resolve_package_target(
|
||||||
package_json_path.as_ref().unwrap(),
|
package_json_path.as_ref().unwrap(),
|
||||||
target,
|
target,
|
||||||
best_match_subpath.unwrap(),
|
&best_match_subpath.unwrap(),
|
||||||
best_match.to_string(),
|
best_match,
|
||||||
referrer,
|
referrer,
|
||||||
referrer_kind,
|
referrer_kind,
|
||||||
true,
|
true,
|
||||||
|
@ -665,8 +625,8 @@ impl NodeResolver {
|
||||||
fn resolve_package_target_string(
|
fn resolve_package_target_string(
|
||||||
&self,
|
&self,
|
||||||
target: String,
|
target: String,
|
||||||
subpath: String,
|
subpath: &str,
|
||||||
match_: String,
|
match_: &str,
|
||||||
package_json_path: &Path,
|
package_json_path: &Path,
|
||||||
referrer: &ModuleSpecifier,
|
referrer: &ModuleSpecifier,
|
||||||
referrer_kind: NodeModuleKind,
|
referrer_kind: NodeModuleKind,
|
||||||
|
@ -746,9 +706,9 @@ impl NodeResolver {
|
||||||
if subpath.is_empty() {
|
if subpath.is_empty() {
|
||||||
return Ok(resolved_path);
|
return Ok(resolved_path);
|
||||||
}
|
}
|
||||||
if invalid_segment_re.is_match(&subpath) {
|
if invalid_segment_re.is_match(subpath) {
|
||||||
let request = if pattern {
|
let request = if pattern {
|
||||||
match_.replace('*', &subpath)
|
match_.replace('*', subpath)
|
||||||
} else {
|
} else {
|
||||||
format!("{match_}{subpath}")
|
format!("{match_}{subpath}")
|
||||||
};
|
};
|
||||||
|
@ -767,7 +727,7 @@ impl NodeResolver {
|
||||||
});
|
});
|
||||||
return Ok(PathBuf::from(replaced.to_string()));
|
return Ok(PathBuf::from(replaced.to_string()));
|
||||||
}
|
}
|
||||||
Ok(resolved_path.join(&subpath).clean())
|
Ok(resolved_path.join(subpath).clean())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
@ -775,8 +735,8 @@ impl NodeResolver {
|
||||||
&self,
|
&self,
|
||||||
package_json_path: &Path,
|
package_json_path: &Path,
|
||||||
target: Value,
|
target: Value,
|
||||||
subpath: String,
|
subpath: &str,
|
||||||
package_subpath: String,
|
package_subpath: &str,
|
||||||
referrer: &ModuleSpecifier,
|
referrer: &ModuleSpecifier,
|
||||||
referrer_kind: NodeModuleKind,
|
referrer_kind: NodeModuleKind,
|
||||||
pattern: bool,
|
pattern: bool,
|
||||||
|
@ -901,7 +861,7 @@ impl NodeResolver {
|
||||||
pub fn package_exports_resolve(
|
pub fn package_exports_resolve(
|
||||||
&self,
|
&self,
|
||||||
package_json_path: &Path,
|
package_json_path: &Path,
|
||||||
package_subpath: String,
|
package_subpath: &str,
|
||||||
package_exports: &Map<String, Value>,
|
package_exports: &Map<String, Value>,
|
||||||
referrer: &ModuleSpecifier,
|
referrer: &ModuleSpecifier,
|
||||||
referrer_kind: NodeModuleKind,
|
referrer_kind: NodeModuleKind,
|
||||||
|
@ -909,16 +869,16 @@ impl NodeResolver {
|
||||||
mode: NodeResolutionMode,
|
mode: NodeResolutionMode,
|
||||||
permissions: &dyn NodePermissions,
|
permissions: &dyn NodePermissions,
|
||||||
) -> Result<PathBuf, AnyError> {
|
) -> Result<PathBuf, AnyError> {
|
||||||
if package_exports.contains_key(&package_subpath)
|
if package_exports.contains_key(package_subpath)
|
||||||
&& package_subpath.find('*').is_none()
|
&& package_subpath.find('*').is_none()
|
||||||
&& !package_subpath.ends_with('/')
|
&& !package_subpath.ends_with('/')
|
||||||
{
|
{
|
||||||
let target = package_exports.get(&package_subpath).unwrap().to_owned();
|
let target = package_exports.get(package_subpath).unwrap().to_owned();
|
||||||
let resolved = self.resolve_package_target(
|
let resolved = self.resolve_package_target(
|
||||||
package_json_path,
|
package_json_path,
|
||||||
target,
|
target,
|
||||||
"".to_string(),
|
"",
|
||||||
package_subpath.to_string(),
|
package_subpath,
|
||||||
referrer,
|
referrer,
|
||||||
referrer_kind,
|
referrer_kind,
|
||||||
false,
|
false,
|
||||||
|
@ -977,8 +937,8 @@ impl NodeResolver {
|
||||||
let maybe_resolved = self.resolve_package_target(
|
let maybe_resolved = self.resolve_package_target(
|
||||||
package_json_path,
|
package_json_path,
|
||||||
target,
|
target,
|
||||||
best_match_subpath.unwrap(),
|
&best_match_subpath.unwrap(),
|
||||||
best_match.to_string(),
|
best_match,
|
||||||
referrer,
|
referrer,
|
||||||
referrer_kind,
|
referrer_kind,
|
||||||
true,
|
true,
|
||||||
|
@ -1032,7 +992,7 @@ impl NodeResolver {
|
||||||
return self
|
return self
|
||||||
.package_exports_resolve(
|
.package_exports_resolve(
|
||||||
&package_config.path,
|
&package_config.path,
|
||||||
package_subpath,
|
&package_subpath,
|
||||||
exports,
|
exports,
|
||||||
referrer,
|
referrer,
|
||||||
referrer_kind,
|
referrer_kind,
|
||||||
|
@ -1065,9 +1025,30 @@ impl NodeResolver {
|
||||||
// Package match.
|
// Package match.
|
||||||
let package_json =
|
let package_json =
|
||||||
self.load_package_json(permissions, package_json_path)?;
|
self.load_package_json(permissions, package_json_path)?;
|
||||||
|
self.resolve_package_subpath(
|
||||||
|
&package_json,
|
||||||
|
&package_subpath,
|
||||||
|
referrer,
|
||||||
|
referrer_kind,
|
||||||
|
conditions,
|
||||||
|
mode,
|
||||||
|
permissions,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
fn resolve_package_subpath(
|
||||||
|
&self,
|
||||||
|
package_json: &PackageJson,
|
||||||
|
package_subpath: &str,
|
||||||
|
referrer: &ModuleSpecifier,
|
||||||
|
referrer_kind: NodeModuleKind,
|
||||||
|
conditions: &[&str],
|
||||||
|
mode: NodeResolutionMode,
|
||||||
|
permissions: &dyn NodePermissions,
|
||||||
|
) -> Result<Option<PathBuf>, AnyError> {
|
||||||
if let Some(exports) = &package_json.exports {
|
if let Some(exports) = &package_json.exports {
|
||||||
return self
|
let result = self.package_exports_resolve(
|
||||||
.package_exports_resolve(
|
|
||||||
&package_json.path,
|
&package_json.path,
|
||||||
package_subpath,
|
package_subpath,
|
||||||
exports,
|
exports,
|
||||||
|
@ -1076,15 +1057,28 @@ impl NodeResolver {
|
||||||
conditions,
|
conditions,
|
||||||
mode,
|
mode,
|
||||||
permissions,
|
permissions,
|
||||||
)
|
);
|
||||||
.map(Some);
|
match result {
|
||||||
|
Ok(found) => return Ok(Some(found)),
|
||||||
|
Err(exports_err) => {
|
||||||
|
if mode.is_types() && package_subpath == "." {
|
||||||
|
if let Ok(Some(path)) =
|
||||||
|
self.legacy_main_resolve(package_json, referrer_kind, mode)
|
||||||
|
{
|
||||||
|
return Ok(Some(path));
|
||||||
|
} else {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Err(exports_err);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if package_subpath == "." {
|
if package_subpath == "." {
|
||||||
return self.legacy_main_resolve(&package_json, referrer_kind, mode);
|
return self.legacy_main_resolve(package_json, referrer_kind, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
let file_path = package_json.path.parent().unwrap().join(&package_subpath);
|
let file_path = package_json.path.parent().unwrap().join(package_subpath);
|
||||||
|
|
||||||
if mode.is_types() {
|
if mode.is_types() {
|
||||||
let maybe_declaration_path =
|
let maybe_declaration_path =
|
||||||
self.path_to_declaration_path(file_path, referrer_kind);
|
self.path_to_declaration_path(file_path, referrer_kind);
|
||||||
|
@ -1443,14 +1437,14 @@ fn throw_import_not_defined(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn throw_invalid_package_target(
|
fn throw_invalid_package_target(
|
||||||
subpath: String,
|
subpath: &str,
|
||||||
target: String,
|
target: String,
|
||||||
package_json_path: &Path,
|
package_json_path: &Path,
|
||||||
internal: bool,
|
internal: bool,
|
||||||
referrer: &ModuleSpecifier,
|
referrer: &ModuleSpecifier,
|
||||||
) -> AnyError {
|
) -> AnyError {
|
||||||
errors::err_invalid_package_target(
|
errors::err_invalid_package_target(
|
||||||
package_json_path.parent().unwrap().display().to_string(),
|
&package_json_path.parent().unwrap().display().to_string(),
|
||||||
subpath,
|
subpath,
|
||||||
target,
|
target,
|
||||||
internal,
|
internal,
|
||||||
|
@ -1478,7 +1472,7 @@ fn throw_invalid_subpath(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn throw_exports_not_found(
|
fn throw_exports_not_found(
|
||||||
subpath: String,
|
subpath: &str,
|
||||||
package_json_path: &Path,
|
package_json_path: &Path,
|
||||||
referrer: &ModuleSpecifier,
|
referrer: &ModuleSpecifier,
|
||||||
mode: NodeResolutionMode,
|
mode: NodeResolutionMode,
|
||||||
|
|
Loading…
Reference in a new issue