From 42d28a8d2ae46b430d1a6a2fbf11bc0dd81d1f2b Mon Sep 17 00:00:00 2001 From: Boro Sitnikovski Date: Tue, 18 Jun 2019 12:38:04 +0200 Subject: [PATCH 1/4] Avoid usage of unguarded getRangeAt and add eslint rule --- packages/components/src/autocomplete/index.js | 3 +- packages/eslint-plugin/configs/custom.js | 1 + .../__tests__/avoid-unguarded-getrangeat.js | 29 +++++++++++++++++++ .../rules/avoid-unguarded-getrangeat.js | 16 ++++++++++ 4 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 packages/eslint-plugin/rules/__tests__/avoid-unguarded-getrangeat.js create mode 100644 packages/eslint-plugin/rules/avoid-unguarded-getrangeat.js diff --git a/packages/components/src/autocomplete/index.js b/packages/components/src/autocomplete/index.js index aa0f4204fc5c56..41cd2a8c07abc6 100644 --- a/packages/components/src/autocomplete/index.js +++ b/packages/components/src/autocomplete/index.js @@ -139,7 +139,8 @@ function filterOptions( search, options = [], maxResults = 10 ) { } function getCaretRect() { - const range = window.getSelection().getRangeAt( 0 ); + const selection = window.getSelection(); + const range = selection.rangeCount ? selection.getRangeAt( 0 ) : null; if ( range ) { return getRectangleFromRange( range ); diff --git a/packages/eslint-plugin/configs/custom.js b/packages/eslint-plugin/configs/custom.js index a09c22148cc592..05f62b92d5bee9 100644 --- a/packages/eslint-plugin/configs/custom.js +++ b/packages/eslint-plugin/configs/custom.js @@ -8,6 +8,7 @@ module.exports = { '@wordpress/no-unused-vars-before-return': 'error', '@wordpress/valid-sprintf': 'error', '@wordpress/no-base-control-with-label-without-id': 'error', + '@wordpress/avoid-unguarded-getrangeat': 'error', 'no-restricted-syntax': [ 'error', { diff --git a/packages/eslint-plugin/rules/__tests__/avoid-unguarded-getrangeat.js b/packages/eslint-plugin/rules/__tests__/avoid-unguarded-getrangeat.js new file mode 100644 index 00000000000000..f8792363abc057 --- /dev/null +++ b/packages/eslint-plugin/rules/__tests__/avoid-unguarded-getrangeat.js @@ -0,0 +1,29 @@ +/** + * External dependencies + */ +import { RuleTester } from 'eslint'; + +/** + * Internal dependencies + */ +import rule from '../avoid-unguarded-getrangeat'; + +const ruleTester = new RuleTester( { + parserOptions: { + ecmaVersion: 6, + }, +} ); + +ruleTester.run( 'avoid-unguarded-getrangeat', rule, { + valid: [ + { + code: `const selection = window.getSelection(); const range = selection.rangeCount ? selection.getRangeAt( 0 ) : null;`, + }, + ], + invalid: [ + { + code: `window.getSelection().getRangeAt( 0 );`, + errors: [ { message: 'Avoid unguarded getRangeAt' } ], + }, + ], +} ); diff --git a/packages/eslint-plugin/rules/avoid-unguarded-getrangeat.js b/packages/eslint-plugin/rules/avoid-unguarded-getrangeat.js new file mode 100644 index 00000000000000..e74bc775de54f3 --- /dev/null +++ b/packages/eslint-plugin/rules/avoid-unguarded-getrangeat.js @@ -0,0 +1,16 @@ +module.exports = { + meta: { + type: 'problem', + schema: [], + }, + create( context ) { + return { + 'CallExpression[callee.object.callee.object.name="window"][callee.object.callee.property.name="getSelection"][callee.property.name="getRangeAt"]'( node ) { + context.report( { + node, + message: 'Avoid unguarded getRangeAt', + } ); + }, + }; + }, +}; From c78772d51d82b4b0e164168df647eca9c658cca1 Mon Sep 17 00:00:00 2001 From: Boro Sitnikovski Date: Wed, 26 Jun 2019 09:34:16 +0200 Subject: [PATCH 2/4] Address PR comments --- packages/eslint-plugin/README.md | 1 + packages/eslint-plugin/configs/custom.js | 2 +- .../docs/rules/avoid-unguarded-get-range-at.md | 18 ++++++++++++++++++ ...geat.js => avoid-unguarded-get-range-at.js} | 4 ++-- ...geat.js => avoid-unguarded-get-range-at.js} | 0 5 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 packages/eslint-plugin/docs/rules/avoid-unguarded-get-range-at.md rename packages/eslint-plugin/rules/__tests__/{avoid-unguarded-getrangeat.js => avoid-unguarded-get-range-at.js} (81%) rename packages/eslint-plugin/rules/{avoid-unguarded-getrangeat.js => avoid-unguarded-get-range-at.js} (100%) diff --git a/packages/eslint-plugin/README.md b/packages/eslint-plugin/README.md index 2c8ef189000c15..70951d603fe51d 100644 --- a/packages/eslint-plugin/README.md +++ b/packages/eslint-plugin/README.md @@ -55,6 +55,7 @@ Rule|Description|Recommended [react-no-unsafe-timeout](/packages/eslint-plugin/docs/rules/react-no-unsafe-timeout.md)|Disallow unsafe `setTimeout` in component| [valid-sprintf](/packages/eslint-plugin/docs/rules/valid-sprintf.md)|Enforce valid sprintf usage|✓ [no-base-control-with-label-without-id](/packages/eslint-plugin/docs/rules/no-base-control-with-label-without-id.md)| Disallow the usage of BaseControl component with a label prop set but omitting the id property|✓ +[avoid-unguarded-get-range-at](/packages/eslint-plugin/docs/rules/avoid-unguarded-get-range-at.md)| Disallow the usage of unguarded `getRangeAt` calls|✓ ### Legacy diff --git a/packages/eslint-plugin/configs/custom.js b/packages/eslint-plugin/configs/custom.js index 05f62b92d5bee9..2fa8bf4e6b5b41 100644 --- a/packages/eslint-plugin/configs/custom.js +++ b/packages/eslint-plugin/configs/custom.js @@ -8,7 +8,7 @@ module.exports = { '@wordpress/no-unused-vars-before-return': 'error', '@wordpress/valid-sprintf': 'error', '@wordpress/no-base-control-with-label-without-id': 'error', - '@wordpress/avoid-unguarded-getrangeat': 'error', + '@wordpress/avoid-unguarded-get-range-at': 'error', 'no-restricted-syntax': [ 'error', { diff --git a/packages/eslint-plugin/docs/rules/avoid-unguarded-get-range-at.md b/packages/eslint-plugin/docs/rules/avoid-unguarded-get-range-at.md new file mode 100644 index 00000000000000..10604e9c0078b0 --- /dev/null +++ b/packages/eslint-plugin/docs/rules/avoid-unguarded-get-range-at.md @@ -0,0 +1,18 @@ +# Avoid unguarded getRangeAt (avoid-unguarded-get-range-at) + +Some browsers (e.g. Safari) will throw an error when `getRangeAt` is called and there are no ranges in the selection. + +## Rule details + +Example of **incorrect** code for this rule: + +```js +window.getSelection().getRangeAt( 0 ); +``` + +Example of **correct** code for this rule: + +```js +const selection = window.getSelection(); +const range = selection.rangeCount ? selection.getRangeAt( 0 ) : null; +``` diff --git a/packages/eslint-plugin/rules/__tests__/avoid-unguarded-getrangeat.js b/packages/eslint-plugin/rules/__tests__/avoid-unguarded-get-range-at.js similarity index 81% rename from packages/eslint-plugin/rules/__tests__/avoid-unguarded-getrangeat.js rename to packages/eslint-plugin/rules/__tests__/avoid-unguarded-get-range-at.js index f8792363abc057..134100342dc355 100644 --- a/packages/eslint-plugin/rules/__tests__/avoid-unguarded-getrangeat.js +++ b/packages/eslint-plugin/rules/__tests__/avoid-unguarded-get-range-at.js @@ -6,7 +6,7 @@ import { RuleTester } from 'eslint'; /** * Internal dependencies */ -import rule from '../avoid-unguarded-getrangeat'; +import rule from '../avoid-unguarded-get-range-at'; const ruleTester = new RuleTester( { parserOptions: { @@ -14,7 +14,7 @@ const ruleTester = new RuleTester( { }, } ); -ruleTester.run( 'avoid-unguarded-getrangeat', rule, { +ruleTester.run( 'avoid-unguarded-get-range-at', rule, { valid: [ { code: `const selection = window.getSelection(); const range = selection.rangeCount ? selection.getRangeAt( 0 ) : null;`, diff --git a/packages/eslint-plugin/rules/avoid-unguarded-getrangeat.js b/packages/eslint-plugin/rules/avoid-unguarded-get-range-at.js similarity index 100% rename from packages/eslint-plugin/rules/avoid-unguarded-getrangeat.js rename to packages/eslint-plugin/rules/avoid-unguarded-get-range-at.js From afc18a4eb7a6ebfc46fdcd017f532bc77fc47951 Mon Sep 17 00:00:00 2001 From: Andrew Duthie Date: Wed, 26 Jun 2019 13:17:20 -0400 Subject: [PATCH 3/4] ESLint Plugin: Add CHANGELOG entry for avoid-unguarded-get-range-at --- packages/eslint-plugin/CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index 28de7846b5f212..54f4c5ede064f9 100644 --- a/packages/eslint-plugin/CHANGELOG.md +++ b/packages/eslint-plugin/CHANGELOG.md @@ -1,3 +1,9 @@ +## Master + +### New Features + +- New Rule: [`@wordpress/avoid-unguarded-get-range-at`](https://github.com/WordPress/gutenberg/blob/master/packages/eslint-plugin/docs/rules/avoid-unguarded-get-range-at.md) + ## 2.3.0 (2019-06-12) ### Bug Fix From 2bf81299b6977478106ceba49f72597ecbdcd1f3 Mon Sep 17 00:00:00 2001 From: Andrew Duthie Date: Wed, 26 Jun 2019 13:18:50 -0400 Subject: [PATCH 4/4] ESLint Plugin: Rename avoid-unguarded-get-range-at to no-unguarded-get-range-at --- packages/eslint-plugin/CHANGELOG.md | 2 +- packages/eslint-plugin/README.md | 2 +- packages/eslint-plugin/configs/custom.js | 2 +- ...unguarded-get-range-at.md => no-unguarded-get-range-at.md} | 2 +- ...unguarded-get-range-at.js => no-unguarded-get-range-at.js} | 4 ++-- ...unguarded-get-range-at.js => no-unguarded-get-range-at.js} | 0 6 files changed, 6 insertions(+), 6 deletions(-) rename packages/eslint-plugin/docs/rules/{avoid-unguarded-get-range-at.md => no-unguarded-get-range-at.md} (86%) rename packages/eslint-plugin/rules/__tests__/{avoid-unguarded-get-range-at.js => no-unguarded-get-range-at.js} (81%) rename packages/eslint-plugin/rules/{avoid-unguarded-get-range-at.js => no-unguarded-get-range-at.js} (100%) diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index 54f4c5ede064f9..649966f3424fc4 100644 --- a/packages/eslint-plugin/CHANGELOG.md +++ b/packages/eslint-plugin/CHANGELOG.md @@ -2,7 +2,7 @@ ### New Features -- New Rule: [`@wordpress/avoid-unguarded-get-range-at`](https://github.com/WordPress/gutenberg/blob/master/packages/eslint-plugin/docs/rules/avoid-unguarded-get-range-at.md) +- New Rule: [`@wordpress/no-unguarded-get-range-at`](https://github.com/WordPress/gutenberg/blob/master/packages/eslint-plugin/docs/rules/no-unguarded-get-range-at.md) ## 2.3.0 (2019-06-12) diff --git a/packages/eslint-plugin/README.md b/packages/eslint-plugin/README.md index 70951d603fe51d..f6f89c95f10819 100644 --- a/packages/eslint-plugin/README.md +++ b/packages/eslint-plugin/README.md @@ -55,7 +55,7 @@ Rule|Description|Recommended [react-no-unsafe-timeout](/packages/eslint-plugin/docs/rules/react-no-unsafe-timeout.md)|Disallow unsafe `setTimeout` in component| [valid-sprintf](/packages/eslint-plugin/docs/rules/valid-sprintf.md)|Enforce valid sprintf usage|✓ [no-base-control-with-label-without-id](/packages/eslint-plugin/docs/rules/no-base-control-with-label-without-id.md)| Disallow the usage of BaseControl component with a label prop set but omitting the id property|✓ -[avoid-unguarded-get-range-at](/packages/eslint-plugin/docs/rules/avoid-unguarded-get-range-at.md)| Disallow the usage of unguarded `getRangeAt` calls|✓ +[no-unguarded-get-range-at](/packages/eslint-plugin/docs/rules/no-unguarded-get-range-at.md)| Disallow the usage of unguarded `getRangeAt` calls|✓ ### Legacy diff --git a/packages/eslint-plugin/configs/custom.js b/packages/eslint-plugin/configs/custom.js index 2fa8bf4e6b5b41..efb873980b22f4 100644 --- a/packages/eslint-plugin/configs/custom.js +++ b/packages/eslint-plugin/configs/custom.js @@ -8,7 +8,7 @@ module.exports = { '@wordpress/no-unused-vars-before-return': 'error', '@wordpress/valid-sprintf': 'error', '@wordpress/no-base-control-with-label-without-id': 'error', - '@wordpress/avoid-unguarded-get-range-at': 'error', + '@wordpress/no-unguarded-get-range-at': 'error', 'no-restricted-syntax': [ 'error', { diff --git a/packages/eslint-plugin/docs/rules/avoid-unguarded-get-range-at.md b/packages/eslint-plugin/docs/rules/no-unguarded-get-range-at.md similarity index 86% rename from packages/eslint-plugin/docs/rules/avoid-unguarded-get-range-at.md rename to packages/eslint-plugin/docs/rules/no-unguarded-get-range-at.md index 10604e9c0078b0..1dd2e3e3ec44b0 100644 --- a/packages/eslint-plugin/docs/rules/avoid-unguarded-get-range-at.md +++ b/packages/eslint-plugin/docs/rules/no-unguarded-get-range-at.md @@ -1,4 +1,4 @@ -# Avoid unguarded getRangeAt (avoid-unguarded-get-range-at) +# Avoid unguarded getRangeAt (no-unguarded-get-range-at) Some browsers (e.g. Safari) will throw an error when `getRangeAt` is called and there are no ranges in the selection. diff --git a/packages/eslint-plugin/rules/__tests__/avoid-unguarded-get-range-at.js b/packages/eslint-plugin/rules/__tests__/no-unguarded-get-range-at.js similarity index 81% rename from packages/eslint-plugin/rules/__tests__/avoid-unguarded-get-range-at.js rename to packages/eslint-plugin/rules/__tests__/no-unguarded-get-range-at.js index 134100342dc355..b3e0a7592f8f08 100644 --- a/packages/eslint-plugin/rules/__tests__/avoid-unguarded-get-range-at.js +++ b/packages/eslint-plugin/rules/__tests__/no-unguarded-get-range-at.js @@ -6,7 +6,7 @@ import { RuleTester } from 'eslint'; /** * Internal dependencies */ -import rule from '../avoid-unguarded-get-range-at'; +import rule from '../no-unguarded-get-range-at'; const ruleTester = new RuleTester( { parserOptions: { @@ -14,7 +14,7 @@ const ruleTester = new RuleTester( { }, } ); -ruleTester.run( 'avoid-unguarded-get-range-at', rule, { +ruleTester.run( 'no-unguarded-get-range-at', rule, { valid: [ { code: `const selection = window.getSelection(); const range = selection.rangeCount ? selection.getRangeAt( 0 ) : null;`, diff --git a/packages/eslint-plugin/rules/avoid-unguarded-get-range-at.js b/packages/eslint-plugin/rules/no-unguarded-get-range-at.js similarity index 100% rename from packages/eslint-plugin/rules/avoid-unguarded-get-range-at.js rename to packages/eslint-plugin/rules/no-unguarded-get-range-at.js