[BUG] range.bnf incomplete regarding whitespace and "spermies"Β #392
Description
What / Why
There are some discrepancies between what ranges are valid according to the BNF definition and the implementation.
As far as I'm aware, this implementation (or the BNF) is the "canonical" definition for NPM version ranges.
Every range abiding by the BNF is valid according to the implementation, but the implementation also accepts ranges as valid that are not in the BNF.
Where
- Current implementation (master branch - e79ac3a)
- BNF definition in docs: https://docs.npmjs.com/cli/v6/using-npm/semver#range-grammar
- BNF definition in repo: https://github.com/npm/node-semver/blob/master/range.bnf
How
Current Behavior
Implementation allows for whitespace within a "simple" range expression at the start of a "partial", but this does not abide by the BNF grammar.
Steps to Reproduce
Using latest release:
const semver = require('semver')
console.log(semver.validRange('>= 1.2.3 < 1.6.0', {loose: false} )) // >=1.2.3 <1.6.0
console.log(semver.validRange('^ 1.2.3 || ^ 2.4.6', {loose: false})) // >=1.2.3 <1.6.0
And tests involving
node-semver/test/fixtures/range-parse.js
Lines 28 to 34 in e79ac3a
and
node-semver/test/fixtures/range-parse.js
Lines 57 to 60 in e79ac3a
pass, but are not valid according to the BNF.
In particular, there is no whitespace defined between comparison operators and the number:
Lines 6 to 9 in e79ac3a
and the tilde definition does not allow for
>
:Line 10 in e79ac3a
Expected Behavior
Either:
-
The BNF definition is expanded to allow whitespace between
-
The implementation is restricted to match the BNF (e.g. only accept the ranges as valid when "loose"?)
(this obviously has backwards compatibility issues)
-
Document clearly that the implementation can parse and accept ranges outside of those defined in the BNF. (Though, perhaps will only ever return canonical ranges that comply with the BNF?)
If updating the grammar, the following change to be sufficient:
partial ::= ( ' ' )* xr ( '.' xr ( '.' xr qualifier ? )? )?
...
tilde ::= '~' ('>')? partial
Though the range
definition could probably also be updated to reflect how multiple spaces are allowed:
range ::= hyphen | simple ( ( ' ' )+ simple ) * | ''