Skip to content

Commit

Permalink
Downgrade to semver compatible with Node v8 (#1575)
Browse files Browse the repository at this point in the history
* Downgrade to `semver` compatible with Node v8

* update
  • Loading branch information
ota-meshi committed Jul 17, 2021
1 parent 738132c commit 5bbc3fe
Show file tree
Hide file tree
Showing 2 changed files with 207 additions and 2 deletions.
207 changes: 206 additions & 1 deletion lib/rules/no-unsupported-features.js
Expand Up @@ -129,7 +129,7 @@ module.exports = {
* @returns {boolean} `true` if it's supporting.
*/
function isNotSupportingVersion(aCase) {
return !semver.subset(versionRange, getSemverRange(aCase.supported))
return !semverSubset(versionRange, getSemverRange(aCase.supported))
}

/** @type {TemplateListener} */
Expand Down Expand Up @@ -163,3 +163,208 @@ module.exports = {
)
}
}

// TODO replace semver.subset() in the major version.
/**
* semver.subset()
*
* We need to use a copy of the semver source code until a major version upgrade.
*
* @see https://github.com/npm/node-semver/blob/e79ac3a450e8bb504e78b8159e3efc70895699b8/ranges/subset.js#L43
* @license ISC at Isaac Z. Schlueter and Contributors
* https://github.com/npm/node-semver/blob/master/LICENSE
*
* @param {semver.Range} sub
* @param {semver.Range} dom
*/
function semverSubset(sub, dom) {
if (sub === dom) return true

sub = new semver.Range(sub)
dom = new semver.Range(dom)
let sawNonNull = false

// eslint-disable-next-line no-labels
OUTER: for (const simpleSub of sub.set) {
for (const simpleDom of dom.set) {
const isSub = simpleSubset(simpleSub, simpleDom)
sawNonNull = sawNonNull || isSub !== null
// eslint-disable-next-line no-labels
if (isSub) continue OUTER
}
if (sawNonNull) return false
}
return true
}

/**
* @license ISC at Isaac Z. Schlueter and Contributors
* https://github.com/npm/node-semver/blob/master/LICENSE
* @param {readonly semver.Comparator[]} sub
* @param {readonly semver.Comparator[]} dom
*/
function simpleSubset(sub, dom) {
if (sub === dom) return true

/**
* @param {semver.Comparator} c
*/
function isAny(c) {
return Object.keys(c.semver).length === 0
}

if (sub.length === 1 && isAny(sub[0])) {
if (dom.length === 1 && isAny(dom[0])) return true
else sub = [new semver.Comparator('>=0.0.0')]
}

if (dom.length === 1 && isAny(dom[0])) {
dom = [new semver.Comparator('>=0.0.0')]
}

const eqSet = new Set()
let gt, lt
for (const c of sub) {
if (c.operator === '>' || c.operator === '>=') gt = higherGT(gt, c)
else if (c.operator === '<' || c.operator === '<=') lt = lowerLT(lt, c)
else eqSet.add(c.semver)
}

if (eqSet.size > 1) return null

let gtltComp
if (gt && lt) {
gtltComp = semver.compare(gt.semver, lt.semver)
if (gtltComp > 0) return null
else if (gtltComp === 0 && (gt.operator !== '>=' || lt.operator !== '<='))
return null
}

// will iterate one or zero times
for (const eq of eqSet) {
if (gt && !semver.satisfies(eq, String(gt))) return null

if (lt && !semver.satisfies(eq, String(lt))) return null

for (const c of dom) {
if (!semver.satisfies(eq, String(c))) return false
}

return true
}

let higher, lower
let hasDomLT, hasDomGT
// if the subset has a prerelease, we need a comparator in the superset
// with the same tuple and a prerelease, or it's not a subset
let needDomLTPre = lt && lt.semver.prerelease.length ? lt.semver : false
let needDomGTPre = gt && gt.semver.prerelease.length ? gt.semver : false
// exception: <1.2.3-0 is the same as <1.2.3
if (
needDomLTPre &&
needDomLTPre.prerelease.length === 1 &&
lt &&
lt.operator === '<' &&
needDomLTPre.prerelease[0] === 0
) {
needDomLTPre = false
}

for (const c of dom) {
hasDomGT = hasDomGT || c.operator === '>' || c.operator === '>='
hasDomLT = hasDomLT || c.operator === '<' || c.operator === '<='
if (gt) {
if (needDomGTPre) {
if (
c.semver.prerelease &&
c.semver.prerelease.length &&
c.semver.major === needDomGTPre.major &&
c.semver.minor === needDomGTPre.minor &&
c.semver.patch === needDomGTPre.patch
) {
needDomGTPre = false
}
}
if (c.operator === '>' || c.operator === '>=') {
higher = higherGT(gt, c)
if (higher === c && higher !== gt) return false
} else if (
gt.operator === '>=' &&
!semver.satisfies(gt.semver, String(c))
)
return false
}
if (lt) {
if (needDomLTPre) {
if (
c.semver.prerelease &&
c.semver.prerelease.length &&
c.semver.major === needDomLTPre.major &&
c.semver.minor === needDomLTPre.minor &&
c.semver.patch === needDomLTPre.patch
) {
needDomLTPre = false
}
}
if (c.operator === '<' || c.operator === '<=') {
lower = lowerLT(lt, c)
if (lower === c && lower !== lt) return false
} else if (
lt.operator === '<=' &&
!semver.satisfies(lt.semver, String(c))
)
return false
}
if (!c.operator && (lt || gt) && gtltComp !== 0) return false
}

// if there was a < or >, and nothing in the dom, then must be false
// UNLESS it was limited by another range in the other direction.
// Eg, >1.0.0 <1.0.1 is still a subset of <2.0.0
if (gt && hasDomLT && !lt && gtltComp !== 0) return false

if (lt && hasDomGT && !gt && gtltComp !== 0) return false

// we needed a prerelease range in a specific tuple, but didn't get one
// then this isn't a subset. eg >=1.2.3-pre is not a subset of >=1.0.0,
// because it includes prereleases in the 1.2.3 tuple
if (needDomGTPre || needDomLTPre) return false

return true
}

/**
* @license ISC at Isaac Z. Schlueter and Contributors
* https://github.com/npm/node-semver/blob/master/LICENSE
* @param {semver.Comparator | void} a
* @param {semver.Comparator} b
*/
const higherGT = (a, b) => {
if (!a) return b
const comp = semver.compare(a.semver, b.semver)
return comp > 0
? a
: comp < 0
? b
: b.operator === '>' && a.operator === '>='
? b
: a
}

/**
* @license ISC at Isaac Z. Schlueter and Contributors
* https://github.com/npm/node-semver/blob/master/LICENSE
* @param {semver.Comparator | void} a
* @param {semver.Comparator} b
*/
const lowerLT = (a, b) => {
if (!a) return b
const comp = semver.compare(a.semver, b.semver)
return comp < 0
? a
: comp > 0
? b
: b.operator === '<' && a.operator === '<='
? b
: a
}
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -55,7 +55,7 @@
"dependencies": {
"eslint-utils": "^2.1.0",
"natural-compare": "^1.4.0",
"semver": "^7.3.2",
"semver": "^6.3.0",
"vue-eslint-parser": "^7.8.0"
},
"devDependencies": {
Expand Down

0 comments on commit 5bbc3fe

Please sign in to comment.