Description
- I'd be willing to implement a fix
Describe the bug
Getting an invalid version
error when there are multiple instances of semver during resolving a version from npm.
To Reproduce
A full repo with instruction can be found here - https://github.com/GiladShoham/yarn-invalid-version-bug
just
npm i
node index.js
and you see the error
Screenshots
Environment if relevant (please complete the following information):
- OS: [e.g. OSX, Linux, Windows, ...]: osx
- Node version [e.g. 8.15.0, 10.15.1, ...]: 12.15.0
- Yarn version [e.g. 2.0.0-rc1, ...]:
"@yarnpkg/core": "2.4.0",
"@yarnpkg/plugin-npm": "2.4.0",
Additional context
This error is a result of the following:
- when trying to create a new instance of SemVer, semver will check if it's already an instance of semver or if it's a string, otherwise it will throw an
Invalid Version
error.
(This is a dangerous code since you might get an instance of SemVer from another instance of semver in your node modules).
see this code in semver here
An issue about this dangerous check is opened here - yarn's plugin-npm creates a range using
semverUtils.validRange
which resolves semver from @yarn/core - later the plugin-npm creates an instance of semver directly which resolves semver from @yarn/plugin-npm
- once it passes the local instance to the range it get's inside the
range.test
to the constructor of SemVer (from yarn/core) with an instance of semver from plugin-npm. which then throws the above error.
In this repo, I've added "semver": "^6.3.0"
in the package.json to make sure we will have different instances of semver in @yarn/core and @yarn/plugin-npm.
In the real world, this might happen very easily since many projects require semver, and many nested dependencies of a project require semver, so it is up to the package manager to decide what it hoists to the root.
so it's very likely to have different instances of semver between @yarn/core and @yarn/plugin-npm.
A possible solution will be just to expose the SemVer constructor from the semverUtils in the core and use the constructor from there instead of call directly to the semver package in the plugin-npm.