fix: intersects() misses shared prerelease versions#884
Open
MerlijnW70 wants to merge 1 commit into
Open
Conversation
Range.intersects() decomposes two ranges into independent comparator
pairs and requires every pair to intersect. That loses set-level
prerelease licensing, so a range whose lower bound licenses a prerelease
was reported as not intersecting an exact match for that prerelease:
semver.intersects('^1.2.3-alpha', '=1.2.3-alpha') // false
semver.satisfies('1.2.3-alpha', '^1.2.3-alpha') // true
semver.satisfies('1.2.3-alpha', '=1.2.3-alpha') // true
Both ranges contain 1.2.3-alpha, yet intersects() reported no overlap.
The same happens for ~ ranges and the desugared '>=1.2.3-alpha <2.0.0-0'
form.
The pairwise test only ever under-reports, so keep it as a sufficient
condition and, when it fails, recover the missed cases: if one set pins
an exact version, the two sets share a version iff that version satisfies
the whole other set (tested with testSet, which applies prerelease
licensing). Ranges without an exact pin are unaffected, and the `*`
short-circuit is preserved.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
intersects()reports two ranges as non-overlapping even when they demonstrably share a prerelease version. It contradictssatisfies(): both ranges contain the version, yetintersects()says they don't intersect.Reproduction
1.2.3-alphasatisfies both ranges, so they clearly intersect. The same false negative occurs for:Root cause
Range.intersects(classes/range.js) decomposes the two ranges into independent comparator pairs and requires every pair to intersect:Prerelease licensing, however, is a set-level property.
^1.2.3-alphadesugars to>=1.2.3-alpha <2.0.0-0; the>=1.2.3-alphacomparator is what licenses the prerelease1.2.3-alpha. When the exact comparator=1.2.3-alphais paired with<2.0.0-0in isolation,Comparator.intersectsevaluatesnew Range('<2.0.0-0').test('1.2.3-alpha'), which isfalse(a single-comparator range applies the prerelease-tuple exclusion). The sibling>=1.2.3-alphathat would license the prerelease is not visible in that pair, so the whole intersection is wrongly reported empty.Fix
The pairwise check only ever under-reports, so it stays as a sufficient condition. When it fails, recover the missed cases: if one set pins an exact version (a bare
=x.y.z), the two sets share a version iff that version satisfies the whole other set — tested withtestSet, which applies prerelease licensing across all of a set's comparators.This is deliberately conservative:
*/ANYshort-circuit is unchanged.7.8.5over a matrix of range pairs (with and withoutincludePrerelease) shows the fix flips only the genuine false negatives totrue(each backed by a concrete shared version) and changes nothing else.intersects(...) === falsestill has no version satisfying both ranges.Tests
Adds fixture cases in
test/fixtures/range-intersection.js(exercised in both argument orderings) for the fixed cases and for the still-correct negatives (e.g.=1.2.3-alphavs<2.0.0, which has no licensing sibling and must remainfalse). Full suite passes with 100% coverage and lint clean.