diff --git a/ranges/min-version.js b/ranges/min-version.js index 09a65aa3..d9d79574 100644 --- a/ranges/min-version.js +++ b/ranges/min-version.js @@ -49,15 +49,15 @@ const minVersion = (range, loose) => { throw new Error(`Unexpected operation: ${comparator.operator}`) } }) - if (setMin && (!minver || gt(minver, setMin))) { + // Maximum versions are ignored above, so a comparator set that is a null + // set (eg `^1 ^2`) still yields a candidate. Check the candidate against + // the range here rather than once at the end, so that such a set cannot + // mask the minimum of another set in the union. + if (setMin && (!minver || gt(minver, setMin)) && range.test(setMin)) { minver = setMin } } - if (minver && range.test(minver)) { - return minver - } - - return null + return minver } module.exports = minVersion diff --git a/test/ranges/min-version.js b/test/ranges/min-version.js index eeb9b725..984b1aa1 100644 --- a/test/ranges/min-version.js +++ b/test/ranges/min-version.js @@ -64,8 +64,15 @@ test('minimum version in range tests', (t) => { ['>2 || >1.0.0-0', '1.0.0-0.0'], ['>2 || >1.0.0-beta', '1.0.0-beta.0'], + // A null set in a union must not mask the minimum of the other sets + ['^1 ^2 || >=3', '3.0.0'], + ['>=2 <1 || >=3', '3.0.0'], + ['1.x 2.x || >=3', '3.0.0'], + ['>=3 || ^1 ^2', '3.0.0'], + // Impossible range ['>4 <3', null], + ['^1 ^2 || >4 <3', null], ].forEach((tuple) => { const range = tuple[0] const version = tuple[1]