-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix: 'yarn --flat' unbound transitive deps shouldn't conflict with top level deps #4488
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good but I have some suggestions.
Also, I'm wondering if we can put this logic into .find()
itself, potentially avoiding some more network requests and the extra loop over dependencies at the end.
src/package-resolver.js
Outdated
// https://github.com/yarnpkg/yarn/issues/79 | ||
const anyLocked = patterns.some(pattern => this.lockfile.getLocked(pattern)); | ||
if (anyLocked) { | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not exclude only the locked ones and still optimize the rest?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I've made this change, but it causes some workspace related tests to fail ("install should link workspaces that refer each other", "install should not link workspaces that refer not compatible version of another workspace"). I don't quite understand why these are failing, but I've just disabled the optimization wherever remote.type === "workspace"
. Open to other suggestions.
src/package-resolver.js
Outdated
return; | ||
} | ||
|
||
const manifestByVersion: Map<string, Manifest> = new Map(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like you just need this.getAllInfoForPackageName(name)
above instead.
src/package-resolver.js
Outdated
}); | ||
|
||
// reverse sort, so we'll find the maximum satisfying version | ||
const availableVersions = [...manifestByVersion.keys()]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not Array.from(manifestByVersion.keys())
. That said spread looks is faster in latest V8 versions so NVM: https://jsperf.com/set-iterator-vs-foreach/4
src/package-resolver.js
Outdated
const availableVersions = [...manifestByVersion.keys()]; | ||
availableVersions.sort(semver.rcompare); | ||
|
||
const requiredRanges = patterns.map(p => normalizePattern(p).range); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can leverage some semver secrets as follows:
const fullRange = patterns.map(pattern => normalizePattern(p).range).join(' ');
const oneRingToRuleThemAll = semver.maxSatisfying([...manifestByVersion.keys()], fullRange);
if (oneRingToRuleThemAll) {
this.collapseAllVersionsOfPackage(name, oneRingToRuleThemAll);
}
This should be more efficient than what the code below does. Also, the code below continuously resolves to new versions as it goes on since return
in a forEach
loop doesn't terminate the loop at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, that's a nice optimization.
This change will decrease the build size from 9.7 MB to 9.7 MB, a decrease of 1.79 KB (0%)
|
This change will increase the build size from 9.69 MB to 9.7 MB, an increase of 870 bytes (0%)
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/package-resolver.js
Outdated
const remote = this.patterns[pattern]._remote; | ||
return !this.lockfile.getLocked(pattern) && (!remote || remote.type !== 'workspace'); | ||
}); | ||
if (collapsablePatterns.length === 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, maybe this should be < 2
since if you have only one pattern, you still don't need to collapse it, right?
src/package-resolver.js
Outdated
@@ -530,10 +545,37 @@ export default class PackageResolver { | |||
this.resolveToResolution(req); | |||
} | |||
|
|||
deps.forEach(dep => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For loops are more efficient so I strongly recommend writing this as a for loop. .forEach
becomes as fast only after Node 8.5.
Waiting other's input. The final version LGTM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense to me. I think the ideal fix would rather be in the hoister (we broke part of it somewhere in 0.26, which is why we noticed some packages stopped being merged together since this release), but it seems like a valid iteration for the time being.
**Summary** Fixes #4550. The optimization introduced in #4488 should only apply to flat installations since even if a single pattern can satisfy all resolved versions, it is not guaranteed that it is strict enough for resolving correctly for all patterns under all circumstances. **Test plan** Manual verification.
**Summary** Fixes #4550. The optimization introduced in #4488 should only apply to flat installations since even if a single pattern can satisfy all resolved versions, it is not guaranteed that it is strict enough for resolving correctly for all patterns under all circumstances. **Test plan** Manual verification.
…el dependency (yarnpkg#4488) **Summary** Fixes yarnpkg#3780, and makes the failing test from yarnpkg#3779 passing. As a final step of package resolution, for each dependency we check whether any version satisfies all resolved version ranges. **Test plan** Fixes an existing (failing) test: "unbound transitive dependencies should not conflict with top level dependency"
**Summary** Fixes yarnpkg#4550. The optimization introduced in yarnpkg#4488 should only apply to flat installations since even if a single pattern can satisfy all resolved versions, it is not guaranteed that it is strict enough for resolving correctly for all patterns under all circumstances. **Test plan** Manual verification.
Summary
Fixes #3780, and makes the failing test from #3779 passing.
As a final step of package resolution, for each dependency we check whether any version satisfies all resolved version ranges.
Test plan
Fixes an existing (failing) test: "unbound transitive dependencies should not conflict with top level dependency"