diff --git a/CHANGELOG.md b/CHANGELOG.md index 7891e9d2ea..108b138dbb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,10 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange * [`jsx-key`]: prevent false "missing array key" warning ([#3215][] @ljharb) * [`jsx-indent`]: avoid checking returns sans jsx ([#3218][] @ljharb) * [`jsx-key`]: avoid a crash ([#3220][] @ljharb) +* version settings: avoid a crash with an invalid version ([#3219][] @ljharb) [#3220]: https://github.com/yannickcr/eslint-plugin-react/issues/3220 +[#3219]: https://github.com/yannickcr/eslint-plugin-react/issues/3219 [#3218]: https://github.com/yannickcr/eslint-plugin-react/issues/3218 [#3215]: https://github.com/yannickcr/eslint-plugin-react/issues/3215 diff --git a/lib/util/version.js b/lib/util/version.js index c762e02bd0..975b76d5fe 100644 --- a/lib/util/version.js +++ b/lib/util/version.js @@ -70,8 +70,10 @@ function detectReactVersion(context) { } } +const defaultVersion = '999.999.999'; + function getReactVersionFromContext(context) { - let confVer = '999.999.999'; + let confVer = defaultVersion; // .eslintrc shared settings (https://eslint.org/docs/user-guide/configuring#adding-shared-settings) if (context.settings && context.settings.react && context.settings.react.version) { let settingsVersion = context.settings.react.version; @@ -89,7 +91,11 @@ function getReactVersionFromContext(context) { warnedForMissingVersion = true; } confVer = /^[0-9]+\.[0-9]+$/.test(confVer) ? `${confVer}.0` : confVer; - return semver.coerce(confVer.split('.').map((part) => Number(part)).join('.')).version; + const result = semver.coerce(confVer.split('.').map((part) => Number(part)).join('.')); + if (!result) { + error(`Warning: React version specified in eslint-plugin-react-settings must be a valid semver version, or "detect"; got “${confVer}”`); + } + return result ? result.version : defaultVersion; } // TODO, semver-major: remove context fallback @@ -111,7 +117,7 @@ function detectFlowVersion(context) { } function getFlowVersionFromContext(context) { - let confVer = '999.999.999'; + let confVer = defaultVersion; // .eslintrc shared settings (https://eslint.org/docs/user-guide/configuring#adding-shared-settings) if (context.settings.react && context.settings.react.flowVersion) { let flowVersion = context.settings.react.flowVersion; @@ -127,7 +133,11 @@ function getFlowVersionFromContext(context) { throw 'Could not retrieve flowVersion from settings'; // eslint-disable-line no-throw-literal } confVer = /^[0-9]+\.[0-9]+$/.test(confVer) ? `${confVer}.0` : confVer; - return semver.coerce(confVer.split('.').map((part) => Number(part)).join('.')).version; + const result = semver.coerce(confVer.split('.').map((part) => Number(part)).join('.')); + if (!result) { + error(`Warning: Flow version specified in eslint-plugin-react-settings must be a valid semver version, or "detect"; got “${confVer}”`); + } + return result ? result.version : defaultVersion; } function test(semverRange, confVer) { diff --git a/tests/util/version.js b/tests/util/version.js index a0bfe06252..ad9bd4585c 100644 --- a/tests/util/version.js +++ b/tests/util/version.js @@ -103,6 +103,7 @@ describe('Version', () => { describe('string version', () => { const context = { settings: { react: { version: '15.0', flowVersion: '1.2' } } }; + const invalidContext = { settings: { react: { version: 'latest', flowVersion: 'not semver' } } }; it('works with react', () => { assert.equal(versionUtil.testReactVersion(context, '>= 0.14.0'), true); @@ -115,6 +116,20 @@ describe('Version', () => { assert.equal(versionUtil.testFlowVersion(context, '>= 1.2.0'), true); assert.equal(versionUtil.testFlowVersion(context, '>= 1.3.0'), false); }); + + it('fails nicely with an invalid react version', () => { + assert.equal(versionUtil.testReactVersion(invalidContext, '>= 15.0'), true); + expectedErrorArgs = [ + ['Warning: React version specified in eslint-plugin-react-settings must be a valid semver version, or "detect"; got “latest”'], + ]; + }); + + it('fails nicely with an invalid flow version', () => { + assert.equal(versionUtil.testFlowVersion(invalidContext, '>= 1.0'), true); + expectedErrorArgs = [ + ['Warning: Flow version specified in eslint-plugin-react-settings must be a valid semver version, or "detect"; got “not semver”'], + ]; + }); }); describe('non-string version', () => {