mirror of
https://github.com/denoland/deno.git
synced 2024-11-25 15:29:32 -05:00
fix(npm): handle an npm package that has itself as a dependency (#17425)
I'm not sure this properly handles scenarios where an npm package uses an alias that resolves to itself, we can fix that if we find a package that actually depends on that behavior. Closes #17420
This commit is contained in:
parent
d5627da552
commit
dde5d9c802
1 changed files with 75 additions and 11 deletions
|
@ -303,6 +303,7 @@ impl Graph {
|
|||
parent_id: &NpmPackageId,
|
||||
) {
|
||||
let mut child = (*child).lock();
|
||||
assert_ne!(child.id, *parent_id);
|
||||
let mut parent = (**self.packages.get(parent_id).unwrap_or_else(|| {
|
||||
panic!(
|
||||
"could not find {} in list of packages when setting child {}",
|
||||
|
@ -311,7 +312,6 @@ impl Graph {
|
|||
)
|
||||
}))
|
||||
.lock();
|
||||
assert_ne!(parent.id, child.id);
|
||||
parent
|
||||
.children
|
||||
.insert(specifier.to_string(), child.id.clone());
|
||||
|
@ -476,7 +476,7 @@ impl<'a, TNpmRegistryApi: NpmRegistryApi>
|
|||
package_req: &NpmPackageReq,
|
||||
package_info: &NpmPackageInfo,
|
||||
) -> Result<(), AnyError> {
|
||||
let node = self.resolve_node_from_info(
|
||||
let (_, node) = self.resolve_node_from_info(
|
||||
&package_req.name,
|
||||
package_req,
|
||||
package_info,
|
||||
|
@ -498,7 +498,7 @@ impl<'a, TNpmRegistryApi: NpmRegistryApi>
|
|||
parent_id: &NpmPackageId,
|
||||
visited_versions: &Arc<VisitedVersionsPath>,
|
||||
) -> Result<Arc<Mutex<Node>>, AnyError> {
|
||||
let node = self.resolve_node_from_info(
|
||||
let (id, node) = self.resolve_node_from_info(
|
||||
&entry.name,
|
||||
match entry.kind {
|
||||
NpmDependencyEntryKind::Dep => &entry.version_req,
|
||||
|
@ -514,12 +514,17 @@ impl<'a, TNpmRegistryApi: NpmRegistryApi>
|
|||
package_info,
|
||||
Some(parent_id),
|
||||
)?;
|
||||
self.graph.set_child_parent(
|
||||
&entry.bare_specifier,
|
||||
&node,
|
||||
&NodeParent::Node(parent_id.clone()),
|
||||
);
|
||||
self.try_add_pending_unresolved_node(Some(visited_versions), &node);
|
||||
// Some packages may resolves to themselves as a dependency. If this occurs,
|
||||
// just ignore adding these as dependencies because this is likely a mistake
|
||||
// in the package.
|
||||
if id != *parent_id {
|
||||
self.graph.set_child_parent(
|
||||
&entry.bare_specifier,
|
||||
&node,
|
||||
&NodeParent::Node(parent_id.clone()),
|
||||
);
|
||||
self.try_add_pending_unresolved_node(Some(visited_versions), &node);
|
||||
}
|
||||
Ok(node)
|
||||
}
|
||||
|
||||
|
@ -555,7 +560,7 @@ impl<'a, TNpmRegistryApi: NpmRegistryApi>
|
|||
version_matcher: &impl NpmVersionMatcher,
|
||||
package_info: &NpmPackageInfo,
|
||||
parent_id: Option<&NpmPackageId>,
|
||||
) -> Result<Arc<Mutex<Node>>, AnyError> {
|
||||
) -> Result<(NpmPackageId, Arc<Mutex<Node>>), AnyError> {
|
||||
let version_and_info = self
|
||||
.resolve_best_package_version_and_info(version_matcher, package_info)?;
|
||||
let id = NpmPackageId {
|
||||
|
@ -587,7 +592,7 @@ impl<'a, TNpmRegistryApi: NpmRegistryApi>
|
|||
node.no_peers = node.deps.is_empty();
|
||||
}
|
||||
|
||||
Ok(node)
|
||||
Ok((id, node))
|
||||
}
|
||||
|
||||
pub async fn resolve_pending(&mut self) -> Result<(), AnyError> {
|
||||
|
@ -2655,6 +2660,65 @@ mod test {
|
|||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn package_has_self_as_dependency() {
|
||||
let api = TestNpmRegistryApi::default();
|
||||
api.ensure_package_version("package-a", "1.0.0");
|
||||
api.add_dependency(("package-a", "1.0.0"), ("package-a", "1"));
|
||||
|
||||
let (packages, package_reqs) =
|
||||
run_resolver_and_get_output(api, vec!["npm:package-a@1.0"]).await;
|
||||
assert_eq!(
|
||||
packages,
|
||||
vec![NpmResolutionPackage {
|
||||
id: NpmPackageId::from_serialized("package-a@1.0.0").unwrap(),
|
||||
copy_index: 0,
|
||||
// in this case, we just ignore that the package did this
|
||||
dependencies: Default::default(),
|
||||
dist: Default::default(),
|
||||
}]
|
||||
);
|
||||
assert_eq!(
|
||||
package_reqs,
|
||||
vec![("package-a@1.0".to_string(), "package-a@1.0.0".to_string())]
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn package_has_self_but_different_version_as_dependency() {
|
||||
let api = TestNpmRegistryApi::default();
|
||||
api.ensure_package_version("package-a", "1.0.0");
|
||||
api.ensure_package_version("package-a", "0.5.0");
|
||||
api.add_dependency(("package-a", "1.0.0"), ("package-a", "^0.5"));
|
||||
|
||||
let (packages, package_reqs) =
|
||||
run_resolver_and_get_output(api, vec!["npm:package-a@1.0"]).await;
|
||||
assert_eq!(
|
||||
packages,
|
||||
vec![
|
||||
NpmResolutionPackage {
|
||||
id: NpmPackageId::from_serialized("package-a@0.5.0").unwrap(),
|
||||
copy_index: 0,
|
||||
dependencies: Default::default(),
|
||||
dist: Default::default(),
|
||||
},
|
||||
NpmResolutionPackage {
|
||||
id: NpmPackageId::from_serialized("package-a@1.0.0").unwrap(),
|
||||
copy_index: 0,
|
||||
dependencies: HashMap::from([(
|
||||
"package-a".to_string(),
|
||||
NpmPackageId::from_serialized("package-a@0.5.0").unwrap(),
|
||||
)]),
|
||||
dist: Default::default(),
|
||||
},
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
package_reqs,
|
||||
vec![("package-a@1.0".to_string(), "package-a@1.0.0".to_string())]
|
||||
);
|
||||
}
|
||||
|
||||
async fn run_resolver_and_get_output(
|
||||
api: TestNpmRegistryApi,
|
||||
reqs: Vec<&str>,
|
||||
|
|
Loading…
Reference in a new issue