@@ -129,7 +129,7 @@ module.exports = {
129
129
* @returns {boolean } `true` if it's supporting.
130
130
*/
131
131
function isNotSupportingVersion ( aCase ) {
132
- return ! semver . subset ( versionRange , getSemverRange ( aCase . supported ) )
132
+ return ! semverSubset ( versionRange , getSemverRange ( aCase . supported ) )
133
133
}
134
134
135
135
/** @type {TemplateListener } */
@@ -163,3 +163,208 @@ module.exports = {
163
163
)
164
164
}
165
165
}
166
+
167
+ // TODO replace semver.subset() in the major version.
168
+ /**
169
+ * semver.subset()
170
+ *
171
+ * We need to use a copy of the semver source code until a major version upgrade.
172
+ *
173
+ * @see https://github.com/npm/node-semver/blob/e79ac3a450e8bb504e78b8159e3efc70895699b8/ranges/subset.js#L43
174
+ * @license ISC at Isaac Z. Schlueter and Contributors
175
+ * https://github.com/npm/node-semver/blob/master/LICENSE
176
+ *
177
+ * @param {semver.Range } sub
178
+ * @param {semver.Range } dom
179
+ */
180
+ function semverSubset ( sub , dom ) {
181
+ if ( sub === dom ) return true
182
+
183
+ sub = new semver . Range ( sub )
184
+ dom = new semver . Range ( dom )
185
+ let sawNonNull = false
186
+
187
+ // eslint-disable-next-line no-labels
188
+ OUTER: for ( const simpleSub of sub . set ) {
189
+ for ( const simpleDom of dom . set ) {
190
+ const isSub = simpleSubset ( simpleSub , simpleDom )
191
+ sawNonNull = sawNonNull || isSub !== null
192
+ // eslint-disable-next-line no-labels
193
+ if ( isSub ) continue OUTER
194
+ }
195
+ if ( sawNonNull ) return false
196
+ }
197
+ return true
198
+ }
199
+
200
+ /**
201
+ * @license ISC at Isaac Z. Schlueter and Contributors
202
+ * https://github.com/npm/node-semver/blob/master/LICENSE
203
+ * @param {readonly semver.Comparator[] } sub
204
+ * @param {readonly semver.Comparator[] } dom
205
+ */
206
+ function simpleSubset ( sub , dom ) {
207
+ if ( sub === dom ) return true
208
+
209
+ /**
210
+ * @param {semver.Comparator } c
211
+ */
212
+ function isAny ( c ) {
213
+ return Object . keys ( c . semver ) . length === 0
214
+ }
215
+
216
+ if ( sub . length === 1 && isAny ( sub [ 0 ] ) ) {
217
+ if ( dom . length === 1 && isAny ( dom [ 0 ] ) ) return true
218
+ else sub = [ new semver . Comparator ( '>=0.0.0' ) ]
219
+ }
220
+
221
+ if ( dom . length === 1 && isAny ( dom [ 0 ] ) ) {
222
+ dom = [ new semver . Comparator ( '>=0.0.0' ) ]
223
+ }
224
+
225
+ const eqSet = new Set ( )
226
+ let gt , lt
227
+ for ( const c of sub ) {
228
+ if ( c . operator === '>' || c . operator === '>=' ) gt = higherGT ( gt , c )
229
+ else if ( c . operator === '<' || c . operator === '<=' ) lt = lowerLT ( lt , c )
230
+ else eqSet . add ( c . semver )
231
+ }
232
+
233
+ if ( eqSet . size > 1 ) return null
234
+
235
+ let gtltComp
236
+ if ( gt && lt ) {
237
+ gtltComp = semver . compare ( gt . semver , lt . semver )
238
+ if ( gtltComp > 0 ) return null
239
+ else if ( gtltComp === 0 && ( gt . operator !== '>=' || lt . operator !== '<=' ) )
240
+ return null
241
+ }
242
+
243
+ // will iterate one or zero times
244
+ for ( const eq of eqSet ) {
245
+ if ( gt && ! semver . satisfies ( eq , String ( gt ) ) ) return null
246
+
247
+ if ( lt && ! semver . satisfies ( eq , String ( lt ) ) ) return null
248
+
249
+ for ( const c of dom ) {
250
+ if ( ! semver . satisfies ( eq , String ( c ) ) ) return false
251
+ }
252
+
253
+ return true
254
+ }
255
+
256
+ let higher , lower
257
+ let hasDomLT , hasDomGT
258
+ // if the subset has a prerelease, we need a comparator in the superset
259
+ // with the same tuple and a prerelease, or it's not a subset
260
+ let needDomLTPre = lt && lt . semver . prerelease . length ? lt . semver : false
261
+ let needDomGTPre = gt && gt . semver . prerelease . length ? gt . semver : false
262
+ // exception: <1.2.3-0 is the same as <1.2.3
263
+ if (
264
+ needDomLTPre &&
265
+ needDomLTPre . prerelease . length === 1 &&
266
+ lt &&
267
+ lt . operator === '<' &&
268
+ needDomLTPre . prerelease [ 0 ] === 0
269
+ ) {
270
+ needDomLTPre = false
271
+ }
272
+
273
+ for ( const c of dom ) {
274
+ hasDomGT = hasDomGT || c . operator === '>' || c . operator === '>='
275
+ hasDomLT = hasDomLT || c . operator === '<' || c . operator === '<='
276
+ if ( gt ) {
277
+ if ( needDomGTPre ) {
278
+ if (
279
+ c . semver . prerelease &&
280
+ c . semver . prerelease . length &&
281
+ c . semver . major === needDomGTPre . major &&
282
+ c . semver . minor === needDomGTPre . minor &&
283
+ c . semver . patch === needDomGTPre . patch
284
+ ) {
285
+ needDomGTPre = false
286
+ }
287
+ }
288
+ if ( c . operator === '>' || c . operator === '>=' ) {
289
+ higher = higherGT ( gt , c )
290
+ if ( higher === c && higher !== gt ) return false
291
+ } else if (
292
+ gt . operator === '>=' &&
293
+ ! semver . satisfies ( gt . semver , String ( c ) )
294
+ )
295
+ return false
296
+ }
297
+ if ( lt ) {
298
+ if ( needDomLTPre ) {
299
+ if (
300
+ c . semver . prerelease &&
301
+ c . semver . prerelease . length &&
302
+ c . semver . major === needDomLTPre . major &&
303
+ c . semver . minor === needDomLTPre . minor &&
304
+ c . semver . patch === needDomLTPre . patch
305
+ ) {
306
+ needDomLTPre = false
307
+ }
308
+ }
309
+ if ( c . operator === '<' || c . operator === '<=' ) {
310
+ lower = lowerLT ( lt , c )
311
+ if ( lower === c && lower !== lt ) return false
312
+ } else if (
313
+ lt . operator === '<=' &&
314
+ ! semver . satisfies ( lt . semver , String ( c ) )
315
+ )
316
+ return false
317
+ }
318
+ if ( ! c . operator && ( lt || gt ) && gtltComp !== 0 ) return false
319
+ }
320
+
321
+ // if there was a < or >, and nothing in the dom, then must be false
322
+ // UNLESS it was limited by another range in the other direction.
323
+ // Eg, >1.0.0 <1.0.1 is still a subset of <2.0.0
324
+ if ( gt && hasDomLT && ! lt && gtltComp !== 0 ) return false
325
+
326
+ if ( lt && hasDomGT && ! gt && gtltComp !== 0 ) return false
327
+
328
+ // we needed a prerelease range in a specific tuple, but didn't get one
329
+ // then this isn't a subset. eg >=1.2.3-pre is not a subset of >=1.0.0,
330
+ // because it includes prereleases in the 1.2.3 tuple
331
+ if ( needDomGTPre || needDomLTPre ) return false
332
+
333
+ return true
334
+ }
335
+
336
+ /**
337
+ * @license ISC at Isaac Z. Schlueter and Contributors
338
+ * https://github.com/npm/node-semver/blob/master/LICENSE
339
+ * @param {semver.Comparator | void } a
340
+ * @param {semver.Comparator } b
341
+ */
342
+ const higherGT = ( a , b ) => {
343
+ if ( ! a ) return b
344
+ const comp = semver . compare ( a . semver , b . semver )
345
+ return comp > 0
346
+ ? a
347
+ : comp < 0
348
+ ? b
349
+ : b . operator === '>' && a . operator === '>='
350
+ ? b
351
+ : a
352
+ }
353
+
354
+ /**
355
+ * @license ISC at Isaac Z. Schlueter and Contributors
356
+ * https://github.com/npm/node-semver/blob/master/LICENSE
357
+ * @param {semver.Comparator | void } a
358
+ * @param {semver.Comparator } b
359
+ */
360
+ const lowerLT = ( a , b ) => {
361
+ if ( ! a ) return b
362
+ const comp = semver . compare ( a . semver , b . semver )
363
+ return comp < 0
364
+ ? a
365
+ : comp > 0
366
+ ? b
367
+ : b . operator === '<' && a . operator === '<='
368
+ ? b
369
+ : a
370
+ }
0 commit comments