Skip to content

fix: use the tightest bound in gtr and ltr when a range has redundant bounds - #905

Open
Prafyl wants to merge 1 commit into
npm:mainfrom
Prafyl:fix/outside-redundant-bounds
Open

Prafyl wants to merge 1 commit into
npm:mainfrom
Prafyl:fix/outside-redundant-bounds

Conversation

@Prafyl

@Prafyl Prafyl commented Sep 21, 2026

Copy link
Copy Markdown

Fixes #904

outside() was taking the comparators with the highest and lowest versions as the edges of each set, which breaks when a set has more than one bound on the same side, like >1.0.0 >=2.0.0 <3.0.0 where it used >1.0.0 as the lower edge.

semver.gtr('1.5.0', '>1.0.0 >=2.0.0 <3.0.0') // was true, now false
semver.ltr('1.2.10', '1.2 <1.2.9 || >2.0.0')  // was true, now false

Now it picks the edges by operator instead, the tightest >/>= bound on one side and the tightest </<= on the other, and when two bounds are at the same version it takes the exclusive one. Doing it this way also shows when a set cant match anything, like >=2.0.0 <1.0.0, so a set like that is skipped instead of deciding the result for the whole range. That fixes gtr('3.0.0', '>=2.0.0 <1.0.0 || 1.x') which returned false. If every set is like that it still returns false like before.

Prerelease handling is the same as before, gtr('0.7.2-beta', '0.7.x') is still true.

i checked it against a brute force answer on about 97k random version/range pairs without prereleases, 7.8.5 got 13k of them wrong and this gets none. Added fixtures for both directions, the >/>= tie, and sets that cant match anything. Tests pass with coverage still at 100% and lint is clean.

@Prafyl
Prafyl requested a review from a team as a code owner September 21, 2026 08:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] gtr and ltr are wrong when a range has two bounds on the same side

1 participant