1
1
const Range = require ( '../classes/range.js' )
2
- const { ANY } = require ( '../classes/comparator.js' )
2
+ const Comparator = require ( '../classes/comparator.js' )
3
+ const { ANY } = Comparator
3
4
const satisfies = require ( '../functions/satisfies.js' )
4
5
const compare = require ( '../functions/compare.js' )
5
6
6
7
// Complex range `r1 || r2 || ...` is a subset of `R1 || R2 || ...` iff:
7
- // - Every simple range `r1, r2, ...` is a subset of some `R1, R2, ...`
8
+ // - Every simple range `r1, r2, ...` is a null set, OR
9
+ // - Every simple range `r1, r2, ...` which is not a null set is a subset of
10
+ // some `R1, R2, ...`
8
11
//
9
12
// Simple range `c1 c2 ...` is a subset of simple range `C1 C2 ...` iff:
10
- // - If C is only the ANY comparator
11
- // - return true
12
13
// - If c is only the ANY comparator
13
14
// - If C is only the ANY comparator, return true
14
- // - Else return false
15
+ // - Else if in prerelease mode, return false
16
+ // - else replace c with `[>=0.0.0]`
17
+ // - If C is only the ANY comparator
18
+ // - if in prerelease mode, return true
19
+ // - else replace C with `[>=0.0.0]`
15
20
// - Let EQ be the set of = comparators in c
16
21
// - If EQ is more than one, return true (null set)
17
22
// - Let GT be the highest > or >= comparator in c
18
23
// - Let LT be the lowest < or <= comparator in c
19
24
// - If GT and LT, and GT.semver > LT.semver, return true (null set)
25
+ // - If any C is a = range, and GT or LT are set, return false
20
26
// - If EQ
21
27
// - If GT, and EQ does not satisfy GT, return true (null set)
22
28
// - If LT, and EQ does not satisfy LT, return true (null set)
@@ -25,13 +31,16 @@ const compare = require('../functions/compare.js')
25
31
// - If GT
26
32
// - If GT.semver is lower than any > or >= comp in C, return false
27
33
// - If GT is >=, and GT.semver does not satisfy every C, return false
34
+ // - If GT.semver has a prerelease, and not in prerelease mode
35
+ // - If no C has a prerelease and the GT.semver tuple, return false
28
36
// - If LT
29
37
// - If LT.semver is greater than any < or <= comp in C, return false
30
38
// - If LT is <=, and LT.semver does not satisfy every C, return false
31
- // - If any C is a = range, and GT or LT are set, return false
39
+ // - If GT.semver has a prerelease, and not in prerelease mode
40
+ // - If no C has a prerelease and the LT.semver tuple, return false
32
41
// - Else return true
33
42
34
- const subset = ( sub , dom , options ) => {
43
+ const subset = ( sub , dom , options = { } ) => {
35
44
if ( sub === dom )
36
45
return true
37
46
@@ -60,11 +69,21 @@ const simpleSubset = (sub, dom, options) => {
60
69
if ( sub === dom )
61
70
return true
62
71
63
- if ( dom . length === 1 && dom [ 0 ] . semver === ANY )
64
- return true
72
+ if ( sub . length === 1 && sub [ 0 ] . semver === ANY ) {
73
+ if ( dom . length === 1 && dom [ 0 ] . semver === ANY )
74
+ return true
75
+ else if ( options . includePrerelease )
76
+ sub = [ new Comparator ( '>=0.0.0-0' ) ]
77
+ else
78
+ sub = [ new Comparator ( '>=0.0.0' ) ]
79
+ }
65
80
66
- if ( sub . length === 1 && sub [ 0 ] . semver === ANY )
67
- return dom . length === 1 && dom [ 0 ] . semver === ANY
81
+ if ( dom . length === 1 && dom [ 0 ] . semver === ANY ) {
82
+ if ( options . includePrerelease )
83
+ return true
84
+ else
85
+ dom = [ new Comparator ( '>=0.0.0' ) ]
86
+ }
68
87
69
88
const eqSet = new Set ( )
70
89
let gt , lt
@@ -107,10 +126,32 @@ const simpleSubset = (sub, dom, options) => {
107
126
108
127
let higher , lower
109
128
let hasDomLT , hasDomGT
129
+ // if the subset has a prerelease, we need a comparator in the superset
130
+ // with the same tuple and a prerelease, or it's not a subset
131
+ let needDomLTPre = lt &&
132
+ ! options . includePrerelease &&
133
+ lt . semver . prerelease . length ? lt . semver : false
134
+ let needDomGTPre = gt &&
135
+ ! options . includePrerelease &&
136
+ gt . semver . prerelease . length ? gt . semver : false
137
+ // exception: <1.2.3-0 is the same as <1.2.3
138
+ if ( needDomLTPre && needDomLTPre . prerelease . length === 1 &&
139
+ lt . operator === '<' && needDomLTPre . prerelease [ 0 ] === 0 ) {
140
+ needDomLTPre = false
141
+ }
142
+
110
143
for ( const c of dom ) {
111
144
hasDomGT = hasDomGT || c . operator === '>' || c . operator === '>='
112
145
hasDomLT = hasDomLT || c . operator === '<' || c . operator === '<='
113
146
if ( gt ) {
147
+ if ( needDomGTPre ) {
148
+ if ( c . semver . prerelease && c . semver . prerelease . length &&
149
+ c . semver . major === needDomGTPre . major &&
150
+ c . semver . minor === needDomGTPre . minor &&
151
+ c . semver . patch === needDomGTPre . patch ) {
152
+ needDomGTPre = false
153
+ }
154
+ }
114
155
if ( c . operator === '>' || c . operator === '>=' ) {
115
156
higher = higherGT ( gt , c , options )
116
157
if ( higher === c && higher !== gt )
@@ -119,6 +160,14 @@ const simpleSubset = (sub, dom, options) => {
119
160
return false
120
161
}
121
162
if ( lt ) {
163
+ if ( needDomLTPre ) {
164
+ if ( c . semver . prerelease && c . semver . prerelease . length &&
165
+ c . semver . major === needDomLTPre . major &&
166
+ c . semver . minor === needDomLTPre . minor &&
167
+ c . semver . patch === needDomLTPre . patch ) {
168
+ needDomLTPre = false
169
+ }
170
+ }
122
171
if ( c . operator === '<' || c . operator === '<=' ) {
123
172
lower = lowerLT ( lt , c , options )
124
173
if ( lower === c && lower !== lt )
@@ -139,6 +188,12 @@ const simpleSubset = (sub, dom, options) => {
139
188
if ( lt && hasDomGT && ! gt && gtltComp !== 0 )
140
189
return false
141
190
191
+ // we needed a prerelease range in a specific tuple, but didn't get one
192
+ // then this isn't a subset. eg >=1.2.3-pre is not a subset of >=1.0.0,
193
+ // because it includes prereleases in the 1.2.3 tuple
194
+ if ( needDomGTPre || needDomLTPre )
195
+ return false
196
+
142
197
return true
143
198
}
144
199
0 commit comments