-
Notifications
You must be signed in to change notification settings - Fork 29.9k
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
process: add version constants and compare #19587
process: add version constants and compare #19587
Conversation
lib/internal/process.js
Outdated
minorVersion, | ||
patchVersion, | ||
} = process.release; | ||
const prereleaseTag = process.release.prereleaseTag.replace(/^-/, ''); |
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.
Isn't this replace()
unnecessary since substr(1, ..)
is already done in C++ land?
lib/internal/process.js
Outdated
return -1; | ||
if (prerelease && patch === patchVersion) | ||
return 1; | ||
if (patch > patchVersion) |
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.
Perhaps move these last two conditionals to the top of this section (after the minor version checks) and then drop the patch === patchVersion
check from each of the other three conditionals?
lib/internal/process.js
Outdated
if (prereleaseTag && prereleaseTag === prerelease && | ||
patch === patchVersion) | ||
return 0; | ||
if (prereleaseTag && patch === patchVersion) |
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 the the above two checks could be grouped together under a if (prereleaseTag)
conditional to avoid checking it twice.
I'm not so sure about the usefulness of allowing a single version string argument. I think it's just complicating things and might slow things down if version checks are being done during runtime. |
doc/api/process.md
Outdated
* `tag` {string} The pre-release tag to compare. | ||
* Returns: {number} `-1` if the given version is lower than the release | ||
version, `0` if the given version matches the process version, and `1` | ||
if the given version is greater than the release version. |
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 already explained in #19574 why this design is problematic:
The signum of the result of
compareVersion
seems counter-intuitive to me. In most (if not all) frameworks, a comparator returns a negative result if the first argument (orthis
) is considered to be "before" the second argument, and a positive result if the first argument (orthis
) is considered to be "after" the second argument (see e.g. java.lang.Comparable for a single-argument comparison).compareVersion
contradicts this well-established norm. I would expectcompareVersion(10, 0, 0) >= 0
to return whether this release is v10 or newer, which follows the norm and is intuitive, but #19438 implements the opposite.
In one of your earlier revisions of your comment in that PR, you seemed to agree with me. Is there a reason to stick to the old design?
lib/internal/process.js
Outdated
if (typeof major === 'string') | ||
[major, minor, patch] = major.split('.'); | ||
if (/-/.test(patch)) | ||
[patch, prerelease] = patch.split('-'); |
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.
Both split()
calls are problematic if you are trying to comply with semver, see section 9 of the spec. The prerelease label can contain dots and dashes.
lib/internal/process.js
Outdated
minor = +minor; | ||
patch = +patch; | ||
if (/^-/.test(prerelease)) | ||
prerelease = prerelease.slice(1); |
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 don't think this is correct. As far as I understand the specification, 1.1.0--
is a valid version, where { major: 1, minor: 1, patch: 0, prerelease: '-' }
.
doc/api/process.md
Outdated
* `majorVersion` {number} The major version of Node.js. | ||
* `minorVersion` {number} The minor version of Node.js. | ||
* `patchVersion` {number} The patch version of Node.js. | ||
* `prereleaseTag` {string} The SemVer pre-release tag for Node.js. |
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 guess the name of this property originates from how the variable is called in node.cc
? Is "prerelease tag" a common term for this? The spec does not use it.
Edit: I just saw that https://github.com/npm/node-semver#prerelease-tags also uses this term, so it is probably not a bad choice.
majorVersion: 4, | ||
minorVersion: 4, | ||
patchVersion: 5, | ||
prereleaseTag: '', |
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.
As long as compareVersion
is enumerable, it should be listed here.
To me, the most important questions are: Do we need / want an API like |
doc/api/process.md
Outdated
* `minorVersion` {number} The minor version of Node.js. | ||
* `patchVersion` {number} The patch version of Node.js. | ||
* `prereleaseTag` {string} The SemVer pre-release tag for Node.js. | ||
* `compareVersion` {function} Perform a SemVer comparison to the release |
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.
- Nit:
{function}
->{Function}
(only primitives are lowercased). - We may need to add the function signature here, with all the optional parameters marked with
[]
(nested or not). - I am not sure if this is a common practice to not single out such API in its own section. Let us see what others think.
lib/internal/process.js
Outdated
const prereleaseTag = process.release.prereleaseTag.replace(/^-/, ''); | ||
|
||
process.release.compareVersion = | ||
(major, minor, patch, prerelease = false) => { |
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.
What should happen if all of or some of major, minor, patch
are undefined? Should the function throw or should these arguments be 0
? Currently, it seems they are NaN
in this case.
lib/internal/process.js
Outdated
return 1; | ||
|
||
if (prereleaseTag) { | ||
if (prereleaseTag === prerelease && patch === patchVersion) |
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 would shorten this to something like:
if (prereleaseTag) {
if (patch === patchVersion)
return (prereleaseTag === prerelease ? 0 : 1);
}
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 scratch that. How about this for the entire bottom part?:
if (patch > patchVersion)
return -1;
if (patch < patchVersion)
return 1;
if (prereleaseTag)
return (prereleaseTag === prerelease ? 0 : 1);
if (prerelease)
return -1;
return 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.
and possibly shorten the last two return
s even further to just return (prerelease ? -1 : 0);
lib/internal/process.js
Outdated
if (patch === patchVersion) | ||
return 1; | ||
} | ||
if (prerelease && patch === patchVersion) |
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.
patch === patchVersion
can be removed here if this check is moved to the bottom.
ba49805
to
526836c
Compare
lib/internal/process.js
Outdated
} = process.release; | ||
|
||
process.release.compareVersion = | ||
(major, minor, patch, prerelease = false) => { |
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 the default value for the last parameter here can be removed as it's not necessary and will not affect tag comparisons when it is undefined
instead of false
.
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.
ah hehe, copied from older implementation :p
@tniessen ptal |
#19587 (comment) should probably be addressed, and #19587 (comment) should be discussed. |
b7aef4a
to
bb27e9c
Compare
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.
Mostly LGTM, but left a few comments.
lib/internal/process.js
Outdated
if (typeof minor !== 'number') | ||
throw new ERR_INVALID_ARG_TYPE('minor', 'number', minor); | ||
if (typeof patch !== 'number') | ||
throw new ERR_INVALID_ARG_TYPE('patch', 'number', minor); |
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.
The last argument should be patch
I think.
compareVersion, | ||
} = process.release; | ||
|
||
assert.strictEqual(0, compareVersion(major, minor, patch, tag)); |
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.
Can you change the order of the arguments in these assertions to reflect the assert.strictEqual(actual, expected)
signature.
assert.strictEqual(0, compareVersion(major, minor, patch, tag)); | ||
|
||
assert.strictEqual(-1, compareVersion(major, minor, patch + 1, tag)); | ||
assert.strictEqual(1, compareVersion(major - 1, minor, patch, tag)); |
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 more tests are needed to achieve code coverage - increment/decrement each value and pass bad values for each.
unless anyone objects i think i'll land this on friday |
doc/api/process.md
Outdated
|
||
Perform a SemVer comparison to the release version. | ||
|
||
* `major` {string | number} The major version to compare or a string containing |
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.
A string is not accepted by the function
3913cef
to
4be45cd
Compare
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.
A few nits and one relevant question / note that I think needs to be addressed?
[0, 0, 0, 0], | ||
]) { | ||
common.expectsError(() => { | ||
compareVersion(args[0], args[1], args[2], args[3]); |
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.
Nit: could just ...args
here?
doc/api/process.md
Outdated
@@ -1509,6 +1512,10 @@ tarball. | |||
- `'Argon'` for the 4.x LTS line beginning with 4.2.0. | |||
- `'Boron'` for the 6.x LTS line beginning with 6.9.0. | |||
- `'Carbon'` for the 8.x LTS line beginning with 8.9.1. | |||
* `majorVersion` {number} The major version of Node.js. |
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.
Nit: for consistency, this might be better as "of this release" or something?
doc/api/process.md
Outdated
|
||
* `major` {number} The major version to compare or a string containing the | ||
entire version. | ||
* `minor` {number} The minor version number to compare. |
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.
Nit: can we stick to "version number" or just "version" consistently between the three descriptions for major, minor & patch?
doc/api/process.md
Outdated
|
||
Perform a SemVer comparison to the release version. | ||
|
||
* `major` {number} The major version to compare or a string containing the |
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.
It's totally possible I'm missing something here but I don't see the functionality for
or a string containing the entire version
implemented in this PR. Did I miss something?
4be45cd
to
bd94813
Compare
both times failures are unrelated, I'll land this soonish |
Landed in 91e0f8d |
PR-URL: #19587 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
tagged as |
PR-URL: #19587 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
@rvagg @devsnek could you bring me up to speed as to why this was ultimately closed. Feels like having a numeric I'm +1 that we don't want to pull in any additional semver functionality, unless we go all the way and merge in the library |
|
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passes