Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions benchmarks/bench-inc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
'use strict'

const Benchmark = require('benchmark')
const invalidVersions = require('../test/fixtures/invalid-versions')
const inc = require('../functions/inc')
const validVersions = require('../test/fixtures/valid-versions')
const suite = new Benchmark.Suite()

const cases = validVersions.map(invalid => invalid[0])
const invalidCases = invalidVersions.map(invalid => invalid[0])

for (const test of cases) {
suite.add(`inc(${test})`, function () {
inc(test, 'release')
})
}

for (const test of invalidCases) {
suite.add(`invalid inc(${test})`, function () {
inc(test, 'release')
})
}

suite
.on('cycle', function (event) {
console.log(String(event.target))
})
.run({ async: false })
7 changes: 4 additions & 3 deletions benchmarks/bench-parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

const Benchmark = require('benchmark')
const parse = require('../functions/parse')
const { MAX_SAFE_INTEGER } = require('../internal/constants')
const validVersions = require('../test/fixtures/valid-versions')
const invalidVersions = require('../test/fixtures/invalid-versions')
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 = validVersions.map(invalid => invalid[0])
const invalidCases = invalidVersions.map(invalid => invalid[0])

for (const test of cases) {
suite.add(`parse(${test})`, function () {
Expand Down
28 changes: 28 additions & 0 deletions benchmarks/bench-valid.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
'use strict'

const Benchmark = require('benchmark')
const invalidVersions = require('../test/fixtures/invalid-versions')
const valid = require('../functions/valid')
const validVersions = require('../test/fixtures/valid-versions')
const suite = new Benchmark.Suite()

const cases = validVersions.map(invalid => invalid[0])
const invalidCases = invalidVersions.map(invalid => invalid[0])

for (const test of cases) {
suite.add(`valid(${test})`, function () {
valid(test)
})
}

for (const test of invalidCases) {
suite.add(`invalid valid(${test})`, function () {
valid(test)
})
}

suite
.on('cycle', function (event) {
console.log(String(event.target))
})
.run({ async: false })
23 changes: 15 additions & 8 deletions classes/semver.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@

const parseOptions = require('../internal/parse-options')
const { compareIdentifiers } = require('../internal/identifiers')

function handleErrorOnSemver (semver, errorMessage, noThrow) {
if (!noThrow) {
throw new TypeError(errorMessage)

Check failure on line 12 in classes/semver.js

View workflow job for this annotation

GitHub Actions / Test - Linux - 14.x

Invalid Version: 1.2.3.4

Check failure on line 12 in classes/semver.js

View workflow job for this annotation

GitHub Actions / Test - Linux - 18.x

Invalid Version: 1.2.3.4

Check failure on line 12 in classes/semver.js

View workflow job for this annotation

GitHub Actions / Test - Linux - 22.x

Invalid Version: 1.2.3.4

Check failure on line 12 in classes/semver.js

View workflow job for this annotation

GitHub Actions / Test - macOS - 20.x

Invalid Version: 1.2.3.4

Check failure on line 12 in classes/semver.js

View workflow job for this annotation

GitHub Actions / Test - macOS - 16.x

Invalid Version: 1.2.3.4

Check failure on line 12 in classes/semver.js

View workflow job for this annotation

GitHub Actions / Test - macOS - 18.x

Invalid Version: 1.2.3.4

Check failure on line 12 in classes/semver.js

View workflow job for this annotation

GitHub Actions / Test - Linux - 10.0.0

Invalid Version: 1.2.3.4

Check failure on line 12 in classes/semver.js

View workflow job for this annotation

GitHub Actions / Test - Linux - 16.x

Invalid Version: 1.2.3.4

Check failure on line 12 in classes/semver.js

View workflow job for this annotation

GitHub Actions / Test - Linux - 12.x

Invalid Version: 1.2.3.4

Check failure on line 12 in classes/semver.js

View workflow job for this annotation

GitHub Actions / Test - macOS - 10.0.0

Invalid Version: 1.2.3.4

Check failure on line 12 in classes/semver.js

View workflow job for this annotation

GitHub Actions / Test - Linux - 10.x

Invalid Version: 1.2.3.4

Check failure on line 12 in classes/semver.js

View workflow job for this annotation

GitHub Actions / Test - macOS - 10.x

Invalid Version: 1.2.3.4

Check failure on line 12 in classes/semver.js

View workflow job for this annotation

GitHub Actions / Test - macOS - 12.x

Invalid Version: 1.2.3.4

Check failure on line 12 in classes/semver.js

View workflow job for this annotation

GitHub Actions / Test - macOS - 22.x

Invalid Version: 1.2.3.4

Check failure on line 12 in classes/semver.js

View workflow job for this annotation

GitHub Actions / Test - macOS - 14.x

Invalid Version: 1.2.3.4

Check failure on line 12 in classes/semver.js

View workflow job for this annotation

GitHub Actions / Test - Linux - 20.x

Invalid Version: 1.2.3.4
} else {
semver.errorMessage = errorMessage
}
}

class SemVer {
constructor (version, options) {
options = parseOptions(options)
Expand All @@ -18,13 +27,11 @@
version = version.version
}
} else if (typeof version !== 'string') {
throw new TypeError(`Invalid version. Must be a string. Got type "${typeof version}".`)
return handleErrorOnSemver(this, `Invalid version. Must be a string. Got type "${typeof version}".`, options.noThrow)
}

if (version.length > MAX_LENGTH) {
throw new TypeError(
`version is longer than ${MAX_LENGTH} characters`
)
return handleErrorOnSemver(this, `version is longer than ${MAX_LENGTH} characters`, options.noThrow)
}

debug('SemVer', version, options)
Expand All @@ -37,7 +44,7 @@
const m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL])

if (!m) {
throw new TypeError(`Invalid Version: ${version}`)
return handleErrorOnSemver(this, `Invalid Version: ${version}`, options.noThrow)
}

this.raw = version
Expand All @@ -48,15 +55,15 @@
this.patch = +m[3]

if (this.major > MAX_SAFE_INTEGER || this.major < 0) {
throw new TypeError('Invalid major version')
return handleErrorOnSemver(this, 'Invalid major version', options.noThrow)
}

if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) {
throw new TypeError('Invalid minor version')
return handleErrorOnSemver(this, 'Invalid minor version', options.noThrow)
}

if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) {
throw new TypeError('Invalid patch version')
return handleErrorOnSemver(this, 'Invalid patch version', options.noThrow)
}

// numberify any prerelease numeric ids
Expand Down
20 changes: 16 additions & 4 deletions functions/inc.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
'use strict'

const SemVer = require('../classes/semver')
const parseOptions = require('../internal/parse-options')
const parse = require('./parse')

const inc = (version, release, options, identifier, identifierBase) => {
if (typeof (options) === 'string') {
Expand All @@ -9,11 +11,21 @@ const inc = (version, release, options, identifier, identifierBase) => {
options = undefined
}

const parsedOptions = parseOptions(options)
const parsed = parse(
version instanceof SemVer ? version.version : version,
parsedOptions.noThrow ? parsedOptions : {
...parsedOptions,
noThrow: true,
}
)

if (parsed === null) {
return null
}

try {
return new SemVer(
version instanceof SemVer ? version.version : version,
options
).inc(release, identifier, identifierBase).version
return parsed.inc(release, identifier, identifierBase).version
} catch (er) {
return null
}
Expand Down
16 changes: 12 additions & 4 deletions functions/parse.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
'use strict'

const SemVer = require('../classes/semver')
const parseOptions = require('../internal/parse-options')
const parse = (version, options, throwErrors = false) => {
if (version instanceof SemVer) {
return version
}
try {
return new SemVer(version, options)
} catch (er) {

const parsedOptions = parseOptions(options)
const parsed = new SemVer(version, parsedOptions.noThrow ? parsedOptions : {
...parsedOptions,
noThrow: true,
})

if (parsed.errorMessage) {
if (!throwErrors) {
return null
}
throw er
throw new TypeError(parsed.errorMessage)
}

return parsed
}

module.exports = parse
13 changes: 13 additions & 0 deletions test/classes/semver.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,19 @@ test('invalid version numbers', (t) => {
t.end()
})

test('invalid version numbers without throw', (t) => {
['1.2.3.4', 'NOT VALID', 1.2, null, 'Infinity.NaN.Infinity'].forEach((v) => {
const parsed = new SemVer(v, undefined, false)

t.strictSame(parsed.errorMessage, typeof v === 'string'
? `Invalid Version: ${v}`
: `Invalid version. Must be a string. Got type "${typeof v}".`
)
})

t.end()
})

test('incrementing', t => {
t.plan(increments.length)
increments.forEach(([
Expand Down
15 changes: 14 additions & 1 deletion test/functions/inc.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const increments = require('../fixtures/increments.js')
test('increment versions test', (t) => {
increments.forEach(([pre, what, wanted, options, id, base]) => {
const found = inc(pre, what, options, id, base)
const cmd = `inc(${pre}, ${what}, ${id}, ${base})`
const cmd = `inc(${pre}, ${what}, ${options}, ${id}, ${base})`
t.equal(found, wanted, `${cmd} === ${wanted}`)

const parsed = parse(pre, options)
Expand Down Expand Up @@ -45,3 +45,16 @@ test('increment versions test', (t) => {

t.end()
})

test('special increment version test', (t) => {
[
['1.2.3', 'prepatch', '1.2.4-foo.1', 'foo', '1', undefined],
['1.2.3', 'prepatch', '1.2.4-foo.1', {}, 'foo', '1'],
].forEach(([pre, what, wanted, options, id, base]) => {
const found = inc(pre, what, options, id, base)
const cmd = `inc(${pre}, ${what}, ${options}, ${id}, ${base})`
t.equal(found, wanted, `${cmd} === ${wanted}`)
})

t.end()
})
Loading