@@ -129,7 +129,7 @@ module.exports = {
129129 * @returns {boolean } `true` if it's supporting.
130130 */
131131 function isNotSupportingVersion ( aCase ) {
132- return ! semver . subset ( versionRange , getSemverRange ( aCase . supported ) )
132+ return ! semverSubset ( versionRange , getSemverRange ( aCase . supported ) )
133133 }
134134
135135 /** @type {TemplateListener } */
@@ -163,3 +163,208 @@ module.exports = {
163163 )
164164 }
165165}
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