diff --git a/classes/semver.js b/classes/semver.js index 54381272..97b811f3 100644 --- a/classes/semver.js +++ b/classes/semver.js @@ -307,6 +307,10 @@ class SemVer { while (--i >= 0) { if (typeof this.prerelease[i] === 'number') { this.prerelease[i]++ + // Keep large numeric ids as strings, just like the constructor. + if (this.prerelease[i] >= MAX_SAFE_INTEGER) { + this.prerelease[i] = String(this.prerelease[i]) + } i = -2 } } diff --git a/test/classes/semver.js b/test/classes/semver.js index 61119745..2fd78db6 100644 --- a/test/classes/semver.js +++ b/test/classes/semver.js @@ -123,6 +123,33 @@ test('incrementing', t => { })) }) +test('repeated prerelease increments at the safe integer boundary', t => { + const boundary = Number.MAX_SAFE_INTEGER - 1 + const versions = [ + `1.2.3-${boundary}`, + `1.2.3-beta.${boundary}`, + `1.2.3-beta.${boundary}.gamma`, + ] + + for (const version of versions) { + const instance = new SemVer(version) + let expected = version + + for (let i = 0; i < 4; i++) { + const previous = instance.version + expected = new SemVer(expected).inc('prerelease').version + instance.inc('prerelease') + + t.equal(instance.version, expected, 'matches incrementing a reparsed version') + t.strictSame(instance.prerelease, new SemVer(instance.version).prerelease, + 'keeps the constructor representation of numeric prerelease identifiers') + t.equal(instance.compare(previous), 1, 'each increment increases the version') + } + } + + t.end() +}) + test('invalid increments', (t) => { t.throws( () => new SemVer('1.2.3').inc('prerelease', '', false),