Skip to content
This repository has been archived by the owner on Jan 20, 2022. It is now read-only.

fix: move pathological nest fixing link to PlaceDep #309

Closed
wants to merge 1 commit into from

Conversation

isaacs
Copy link
Contributor

@isaacs isaacs commented Aug 12, 2021

When a dependency graph cycles back on itself incompatibly like this:

a@1 -> b@1
b@1 -> a@2
a@2 -> b@2
b@2 -> a@1

We would find ourselves unable to handle the conflict via nesting. For
example:

root
+-- a@1 -> b@1
+-- b@1 -> a@2
    +-- a@2 -> b@2
    +-- b@2 -> a@1
        +-- a@1 -> b@1
        +-- b@1 -> a@2
            +-- a@2 -> b@2
            +-- b@2 -> a@1 (cycling forever)

In order to address this, we create a link when such a cycle is
detected.

root
+-- a@1 -> b@1
+-- b@1 -> a@2
    +-- a@2 -> b@2
    +-- b@2 -> a@1
        +-- a@1 -> b@1
        +-- b@1 -> link to root/node_modules/b@1

Prior to the recent refactor to move much of the dependency placement
logic out of Arborist.buildIdealTree and into the PlaceDep class, this
link was created right at the moment when a new dependency was created
in a temp tree.

However, if we feed that Link object into the PlaceDep flow, it will
(correctly) see that the Link does not match the Node further up the
tree, and attempt to replace it.

Compounding the problem (and why it appeared in npm dedupe and not
npm install) is the fact that explicitly named updates are always
treated as a "problem edge", so that they can be re-evaluated.

So, rather than creating a Node to be tested against the tree, it was
creating a Link object, and then attempting to replace the Link's target
with the Link itself, which caused some havoc.

This patch moves the loop detection and remediating Link creation into
the PlaceDep class, which is the more proper place for it, as that class
owns the "put deps into the tree" logic, and this is clearly a "put deps
into the tree" type of situation.

Via: @ParadoxInfinite
Close: npm/cli#3632
Close: #308
Fix: npm/cli#3565

References

When a dependency graph cycles back on itself incompatibly like this:

```
a@1 -> b@1
b@1 -> a@2
a@2 -> b@2
b@2 -> a@1
```

We would find ourselves unable to handle the conflict via nesting.  For
example:

```
root
+-- a@1 -> b@1
+-- b@1 -> a@2
    +-- a@2 -> b@2
    +-- b@2 -> a@1
        +-- a@1 -> b@1
        +-- b@1 -> a@2
            +-- a@2 -> b@2
            +-- b@2 -> a@1 (cycling forever)
```

In order to address this, we create a link when such a cycle is
detected.

```
root
+-- a@1 -> b@1
+-- b@1 -> a@2
    +-- a@2 -> b@2
    +-- b@2 -> a@1
        +-- a@1 -> b@1
        +-- b@1 -> link to root/node_modules/b@1
```

Prior to the recent refactor to move much of the dependency placement
logic out of Arborist.buildIdealTree and into the PlaceDep class, this
link was created right at the moment when a new dependency was created
in a temp tree.

However, if we feed that Link object into the PlaceDep flow, it will
(correctly) see that the Link does not match the Node further up the
tree, and attempt to replace it.

Compounding the problem (and why it appeared in `npm dedupe` and not
`npm install`) is the fact that explicitly named updates are _always_
treated as a "problem edge", so that they can be re-evaluated.

So, rather than creating a Node to be tested against the tree, it was
creating a Link object, and then attempting to replace the Link's target
with the Link itself, which caused some havoc.

This patch moves the loop detection and remediating Link creation into
the PlaceDep class, which is the more proper place for it, as that class
owns the "put deps into the tree" logic, and this is clearly a "put deps
into the tree" type of situation.

Via: @ParadoxInfinite
Close: npm/cli#3632
Close: #308
Fix: npm/cli#3565
Copy link
Contributor

@nlf nlf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks good! makes sense to me

@isaacs isaacs closed this in 77e279a Aug 12, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[BUG] npm dedupe fails with TypeError: Cannot read property 'path' of null
2 participants