Skip to content

Commit de78282

Browse files
committed
fix: avoid throw for invalid cases when not needed
1 parent d17aebf commit de78282

File tree

8 files changed

+130
-20
lines changed

8 files changed

+130
-20
lines changed

benchmarks/bench-inc.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
'use strict'
2+
3+
const Benchmark = require('benchmark')
4+
const invalidVersions = require('../test/fixtures/invalid-versions')
5+
const inc = require('../functions/inc')
6+
const validVersions = require('../test/fixtures/valid-versions')
7+
const suite = new Benchmark.Suite()
8+
9+
const cases = validVersions.map(invalid => invalid[0])
10+
const invalidCases = invalidVersions.map(invalid => invalid[0])
11+
12+
for (const test of cases) {
13+
suite.add(`inc(${test})`, function () {
14+
inc(test, 'release')
15+
})
16+
}
17+
18+
for (const test of invalidCases) {
19+
suite.add(`invalid inc(${test})`, function () {
20+
inc(test, 'release')
21+
})
22+
}
23+
24+
suite
25+
.on('cycle', function (event) {
26+
console.log(String(event.target))
27+
})
28+
.run({ async: false })

benchmarks/bench-parse.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22

33
const Benchmark = require('benchmark')
44
const parse = require('../functions/parse')
5-
const { MAX_SAFE_INTEGER } = require('../internal/constants')
5+
const validVersions = require('../test/fixtures/valid-versions')
6+
const invalidVersions = require('../test/fixtures/invalid-versions')
67
const suite = new Benchmark.Suite()
78

8-
const cases = ['1.2.1', '1.2.2-4', '1.2.3-pre']
9-
const invalidCases = [`${MAX_SAFE_INTEGER}0.0.0`, 'hello, world', 'xyz']
9+
const cases = validVersions.map(invalid => invalid[0])
10+
const invalidCases = invalidVersions.map(invalid => invalid[0])
1011

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

benchmarks/bench-valid.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
'use strict'
2+
3+
const Benchmark = require('benchmark')
4+
const invalidVersions = require('../test/fixtures/invalid-versions')
5+
const valid = require('../functions/valid')
6+
const validVersions = require('../test/fixtures/valid-versions')
7+
const suite = new Benchmark.Suite()
8+
9+
const cases = validVersions.map(invalid => invalid[0])
10+
const invalidCases = invalidVersions.map(invalid => invalid[0])
11+
12+
for (const test of cases) {
13+
suite.add(`valid(${test})`, function () {
14+
valid(test)
15+
})
16+
}
17+
18+
for (const test of invalidCases) {
19+
suite.add(`invalid valid(${test})`, function () {
20+
valid(test)
21+
})
22+
}
23+
24+
suite
25+
.on('cycle', function (event) {
26+
console.log(String(event.target))
27+
})
28+
.run({ async: false })

classes/semver.js

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@ const { safeRe: re, t } = require('../internal/re')
66

77
const parseOptions = require('../internal/parse-options')
88
const { compareIdentifiers } = require('../internal/identifiers')
9+
10+
function handleErrorOnSemver (semver, errorMessage, noThrow) {
11+
if (!noThrow) {
12+
throw new TypeError(errorMessage)
13+
} else {
14+
semver.errorMessage = errorMessage
15+
}
16+
}
17+
918
class SemVer {
1019
constructor (version, options) {
1120
options = parseOptions(options)
@@ -18,13 +27,11 @@ class SemVer {
1827
version = version.version
1928
}
2029
} else if (typeof version !== 'string') {
21-
throw new TypeError(`Invalid version. Must be a string. Got type "${typeof version}".`)
30+
return handleErrorOnSemver(this, `Invalid version. Must be a string. Got type "${typeof version}".`, options.noThrow)
2231
}
2332

2433
if (version.length > MAX_LENGTH) {
25-
throw new TypeError(
26-
`version is longer than ${MAX_LENGTH} characters`
27-
)
34+
return handleErrorOnSemver(this, `version is longer than ${MAX_LENGTH} characters`, options.noThrow)
2835
}
2936

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

3946
if (!m) {
40-
throw new TypeError(`Invalid Version: ${version}`)
47+
return handleErrorOnSemver(this, `Invalid Version: ${version}`, options.noThrow)
4148
}
4249

4350
this.raw = version
@@ -48,15 +55,15 @@ class SemVer {
4855
this.patch = +m[3]
4956

5057
if (this.major > MAX_SAFE_INTEGER || this.major < 0) {
51-
throw new TypeError('Invalid major version')
58+
return handleErrorOnSemver(this, 'Invalid major version', options.noThrow)
5259
}
5360

5461
if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) {
55-
throw new TypeError('Invalid minor version')
62+
return handleErrorOnSemver(this, 'Invalid minor version', options.noThrow)
5663
}
5764

5865
if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) {
59-
throw new TypeError('Invalid patch version')
66+
return handleErrorOnSemver(this, 'Invalid patch version', options.noThrow)
6067
}
6168

6269
// numberify any prerelease numeric ids

functions/inc.js

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
'use strict'
22

33
const SemVer = require('../classes/semver')
4+
const parseOptions = require('../internal/parse-options')
5+
const parse = require('./parse')
46

57
const inc = (version, release, options, identifier, identifierBase) => {
68
if (typeof (options) === 'string') {
@@ -9,11 +11,21 @@ const inc = (version, release, options, identifier, identifierBase) => {
911
options = undefined
1012
}
1113

14+
const parsedOptions = parseOptions(options)
15+
const parsed = parse(
16+
version instanceof SemVer ? version.version : version,
17+
parsedOptions.noThrow ? parsedOptions : {
18+
...parsedOptions,
19+
noThrow: true,
20+
}
21+
)
22+
23+
if (parsed === null) {
24+
return null
25+
}
26+
1227
try {
13-
return new SemVer(
14-
version instanceof SemVer ? version.version : version,
15-
options
16-
).inc(release, identifier, identifierBase).version
28+
return parsed.inc(release, identifier, identifierBase).version
1729
} catch (er) {
1830
return null
1931
}

functions/parse.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,26 @@
11
'use strict'
22

33
const SemVer = require('../classes/semver')
4+
const parseOptions = require('../internal/parse-options')
45
const parse = (version, options, throwErrors = false) => {
56
if (version instanceof SemVer) {
67
return version
78
}
8-
try {
9-
return new SemVer(version, options)
10-
} catch (er) {
9+
10+
const parsedOptions = parseOptions(options)
11+
const parsed = new SemVer(version, parsedOptions.noThrow ? parsedOptions : {
12+
...parsedOptions,
13+
noThrow: true,
14+
})
15+
16+
if (parsed.errorMessage) {
1117
if (!throwErrors) {
1218
return null
1319
}
14-
throw er
20+
throw new TypeError(parsed.errorMessage)
1521
}
22+
23+
return parsed
1624
}
1725

1826
module.exports = parse

test/classes/semver.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,19 @@ test('invalid version numbers', (t) => {
9797
t.end()
9898
})
9999

100+
test('invalid version numbers without throw', (t) => {
101+
['1.2.3.4', 'NOT VALID', 1.2, null, 'Infinity.NaN.Infinity'].forEach((v) => {
102+
const parsed = new SemVer(v, undefined, false)
103+
104+
t.strictSame(parsed.errorMessage, typeof v === 'string'
105+
? `Invalid Version: ${v}`
106+
: `Invalid version. Must be a string. Got type "${typeof v}".`
107+
)
108+
})
109+
110+
t.end()
111+
})
112+
100113
test('incrementing', t => {
101114
t.plan(increments.length)
102115
increments.forEach(([

test/functions/inc.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const increments = require('../fixtures/increments.js')
88
test('increment versions test', (t) => {
99
increments.forEach(([pre, what, wanted, options, id, base]) => {
1010
const found = inc(pre, what, options, id, base)
11-
const cmd = `inc(${pre}, ${what}, ${id}, ${base})`
11+
const cmd = `inc(${pre}, ${what}, ${options}, ${id}, ${base})`
1212
t.equal(found, wanted, `${cmd} === ${wanted}`)
1313

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

4646
t.end()
4747
})
48+
49+
test('special increment version test', (t) => {
50+
[
51+
['1.2.3', 'prepatch', '1.2.4-foo.1', 'foo', '1', undefined],
52+
['1.2.3', 'prepatch', '1.2.4-foo.1', {}, 'foo', '1'],
53+
].forEach(([pre, what, wanted, options, id, base]) => {
54+
const found = inc(pre, what, options, id, base)
55+
const cmd = `inc(${pre}, ${what}, ${options}, ${id}, ${base})`
56+
t.equal(found, wanted, `${cmd} === ${wanted}`)
57+
})
58+
59+
t.end()
60+
})

0 commit comments

Comments
 (0)