diff --git a/.github/workflows/post-dependabot.yml b/.github/workflows/post-dependabot.yml index 1ea8693c..3a919116 100644 --- a/.github/workflows/post-dependabot.yml +++ b/.github/workflows/post-dependabot.yml @@ -54,7 +54,7 @@ jobs: else # strip leading slash from directory so it works as a # a path to the workspace flag - echo "workspace=-w ${dependabot_dir#/}" >> $GITHUB_OUTPUT + echo "workspace=--workspace ${dependabot_dir#/}" >> $GITHUB_OUTPUT fi - name: Apply Changes diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 3066f524..32a56fe9 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "7.7.2" + ".": "7.7.3" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 90d1cd1e..518b61bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [7.7.3](https://github.com/npm/node-semver/compare/v7.7.2...v7.7.3) (2025-10-06) +### Bug Fixes +* [`e37e0ca`](https://github.com/npm/node-semver/commit/e37e0ca0b5fc910d2b1948d25dbc83cc3a0921ea) [#813](https://github.com/npm/node-semver/pull/813) faster paths for compare (#813) (@H4ad) +* [`2471d75`](https://github.com/npm/node-semver/commit/2471d7543e2e63d9d95358e2405e7e1cde926c36) [#811](https://github.com/npm/node-semver/pull/811) x-range build metadata support (i529015) +### Chores +* [`8f05c87`](https://github.com/npm/node-semver/commit/8f05c87f56a4123259b8c6d9324f53eadb02e48f) [#807](https://github.com/npm/node-semver/pull/807) bump @npmcli/template-oss from 4.25.0 to 4.25.1 (#807) (@dependabot[bot], @owlstronaut) + ## [7.7.2](https://github.com/npm/node-semver/compare/v7.7.1...v7.7.2) (2025-05-12) ### Bug Fixes * [`fcafb61`](https://github.com/npm/node-semver/commit/fcafb61ed566ff8ccf24818dd94b76738f037aa4) [#780](https://github.com/npm/node-semver/pull/780) add missing `'use strict'` directives (#780) (@Fdawgs) diff --git a/benchmarks/bench-compare.js b/benchmarks/bench-compare.js index 81db8c24..ec75f2d3 100644 --- a/benchmarks/bench-compare.js +++ b/benchmarks/bench-compare.js @@ -4,45 +4,15 @@ const Benchmark = require('benchmark') const SemVer = require('../classes/semver') const suite = new Benchmark.Suite() -const versions = ['1.0.3', '2.2.2', '2.3.0'] -const versionToCompare = '1.0.2' -const option1 = { includePrelease: true } -const option2 = { includePrelease: true, loose: true } -const option3 = { includePrelease: true, loose: true, rtl: true } +const comparisons = require('../test/fixtures/comparisons') -for (const version of versions) { - suite.add(`compare ${version} to ${versionToCompare}`, function () { - const semver = new SemVer(version) - semver.compare(versionToCompare) +for (const [v0, v1] of comparisons) { + suite.add(`compare ${v0} to ${v1}`, function () { + const semver = new SemVer(v0) + semver.compare(v1) }) } -for (const version of versions) { - suite.add( - `compare ${version} to ${versionToCompare} with option (${JSON.stringify(option1)})`, - function () { - const semver = new SemVer(version, option1) - semver.compare(versionToCompare) - }) -} - -for (const version of versions) { - suite.add(`compare ${version} to ${versionToCompare} with option (${JSON.stringify(option2)})`, - function () { - const semver = new SemVer(version, option2) - semver.compare(versionToCompare) - }) -} - -for (const version of versions) { - suite.add( - `compare ${version} to ${versionToCompare} with option (${JSON.stringify(option3)})`, - function () { - const semver = new SemVer(version, option3) - semver.compare(versionToCompare) - }) -} - suite .on('cycle', function (event) { console.log(String(event.target)) diff --git a/benchmarks/bench-parse.js b/benchmarks/bench-parse.js index af10ec52..5756eee2 100644 --- a/benchmarks/bench-parse.js +++ b/benchmarks/bench-parse.js @@ -2,21 +2,20 @@ const Benchmark = require('benchmark') const parse = require('../functions/parse') -const { MAX_SAFE_INTEGER } = require('../internal/constants') const suite = new Benchmark.Suite() -const cases = ['1.2.1', '1.2.2-4', '1.2.3-pre'] -const invalidCases = [`${MAX_SAFE_INTEGER}0.0.0`, 'hello, world', 'xyz'] +const cases = require(`../test/fixtures/valid-versions`) +const invalidCases = require(`../test/fixtures/invalid-versions`) for (const test of cases) { - suite.add(`parse(${test})`, function () { - parse(test) + suite.add(`parse(${test[0]})`, function () { + parse(test[0]) }) } for (const test of invalidCases) { - suite.add(`invalid parse(${test})`, function () { - parse(test) + suite.add(`invalid parse(${test[0]})`, function () { + parse(test[0]) }) } diff --git a/classes/range.js b/classes/range.js index f80c2359..94629ce6 100644 --- a/classes/range.js +++ b/classes/range.js @@ -255,6 +255,7 @@ const isSatisfiable = (comparators, options) => { // already replaced the hyphen ranges // turn into a set of JUST comparators. const parseComparator = (comp, options) => { + comp = comp.replace(re[t.BUILD], '') debug('comp', comp, options) comp = replaceCarets(comp, options) debug('caret', comp) diff --git a/classes/semver.js b/classes/semver.js index 2efba0f4..92254be1 100644 --- a/classes/semver.js +++ b/classes/semver.js @@ -111,11 +111,25 @@ class SemVer { other = new SemVer(other, this.options) } - return ( - compareIdentifiers(this.major, other.major) || - compareIdentifiers(this.minor, other.minor) || - compareIdentifiers(this.patch, other.patch) - ) + if (this.major < other.major) { + return -1 + } + if (this.major > other.major) { + return 1 + } + if (this.minor < other.minor) { + return -1 + } + if (this.minor > other.minor) { + return 1 + } + if (this.patch < other.patch) { + return -1 + } + if (this.patch > other.patch) { + return 1 + } + return 0 } comparePre (other) { diff --git a/internal/identifiers.js b/internal/identifiers.js index a4613dee..d053472d 100644 --- a/internal/identifiers.js +++ b/internal/identifiers.js @@ -2,6 +2,10 @@ const numeric = /^[0-9]+$/ const compareIdentifiers = (a, b) => { + if (typeof a === 'number' && typeof b === 'number') { + return a === b ? 0 : a < b ? -1 : 1 + } + const anum = numeric.test(a) const bnum = numeric.test(b) diff --git a/package.json b/package.json index 1fbef5a9..2b8cadaa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "semver", - "version": "7.7.2", + "version": "7.7.3", "description": "The semantic version parser used by npm.", "main": "index.js", "scripts": { @@ -15,7 +15,7 @@ }, "devDependencies": { "@npmcli/eslint-config": "^5.0.0", - "@npmcli/template-oss": "4.24.3", + "@npmcli/template-oss": "4.25.1", "benchmark": "^2.1.4", "tap": "^16.0.0" }, @@ -52,7 +52,7 @@ "author": "GitHub Inc.", "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.24.3", + "version": "4.25.1", "engines": ">=10", "distPaths": [ "classes/", diff --git a/test/fixtures/range-parse.js b/test/fixtures/range-parse.js index 3fdd5ff2..e4e252d7 100644 --- a/test/fixtures/range-parse.js +++ b/test/fixtures/range-parse.js @@ -88,4 +88,32 @@ module.exports = [ [`^${MAX_SAFE_INTEGER}.0.0`, null], [`=${MAX_SAFE_INTEGER}.0.0`, `${MAX_SAFE_INTEGER}.0.0`], [`^${MAX_SAFE_INTEGER - 1}.0.0`, `>=${MAX_SAFE_INTEGER - 1}.0.0 <${MAX_SAFE_INTEGER}.0.0-0`], + // x-ranges with build metadata + ['1.x.x+build >2.x+build', '>=1.0.0 <2.0.0-0 >=3.0.0', null], + ['>=1.x+build <2.x.x+build', '>=1.0.0 <2.0.0-0', null], + ['1.x.x+build || 2.x.x+build', '>=1.0.0 <2.0.0-0||>=2.0.0 <3.0.0-0', null], + ['1.x+build.123', '>=1.0.0 <2.0.0-0', null], + ['1.x.x+meta-data', '>=1.0.0 <2.0.0-0', null], + ['1.x.x+build.123 >2.x.x+meta-data', '>=1.0.0 <2.0.0-0 >=3.0.0', null], + ['1.x.x+build <2.x.x+meta', '>=1.0.0 <2.0.0-0', null], + ['>1.x+build <=2.x.x+meta', '>=2.0.0 <3.0.0-0', null], + [' 1.x.x+build >2.x.x+build ', '>=1.0.0 <2.0.0-0 >=3.0.0', null], + ['^1.x+build', '>=1.0.0 <2.0.0-0', null], + ['^1.x.x+build', '>=1.0.0 <2.0.0-0', null], + ['^1.2.x+build', '>=1.2.0 <2.0.0-0', null], + ['^1.x+meta-data', '>=1.0.0 <2.0.0-0', null], + ['^1.x.x+build.123', '>=1.0.0 <2.0.0-0', null], + ['~1.x+build', '>=1.0.0 <2.0.0-0', null], + ['~1.x.x+build', '>=1.0.0 <2.0.0-0', null], + ['~1.2.x+build', '>=1.2.0 <1.3.0-0', null], + ['~1.x+meta-data', '>=1.0.0 <2.0.0-0', null], + ['~1.x.x+build.123', '>=1.0.0 <2.0.0-0', null], + ['^1.x.x+build || ~2.x.x+meta', '>=1.0.0 <2.0.0-0||>=2.0.0 <3.0.0-0', null], + ['~1.x.x+build >2.x+meta', '>=1.0.0 <2.0.0-0 >=3.0.0', null], + ['^1.x+build.123 <2.x.x+meta-data', '>=1.0.0 <2.0.0-0', null], + // // x-ranges with prerelease and build + ['1.x.x-alpha+build', '>=1.0.0 <2.0.0-0', null], + ['>1.x.x-alpha+build', '>=2.0.0', null], + ['>=1.x.x-alpha+build <2.x.x+build', '>=1.0.0 <2.0.0-0', null], + ['1.x.x-alpha+build || 2.x.x+build', '>=1.0.0 <2.0.0-0||>=2.0.0 <3.0.0-0', null], ] diff --git a/test/internal/identifiers.js b/test/internal/identifiers.js index 1a89583e..cb217eda 100644 --- a/test/internal/identifiers.js +++ b/test/internal/identifiers.js @@ -8,6 +8,7 @@ test('rcompareIdentifiers and compareIdentifiers', (t) => { ['1', '2'], ['alpha', 'beta'], ['0', 'beta'], + [1, 2], ] set.forEach((ab) => { const a = ab[0] @@ -17,5 +18,7 @@ test('rcompareIdentifiers and compareIdentifiers', (t) => { }) t.equal(compareIdentifiers('0', '0'), 0) t.equal(rcompareIdentifiers('0', '0'), 0) + t.equal(compareIdentifiers(1, 1), 0) + t.equal(rcompareIdentifiers(1, 1), 0) t.end() })