Skip to content

Commit

Permalink
Avoid usage of unguarded getRangeAt and add eslint rule (#16212)
Browse files Browse the repository at this point in the history
* Avoid usage of unguarded getRangeAt and add eslint rule

* Address PR comments

* ESLint Plugin: Add CHANGELOG entry for avoid-unguarded-get-range-at

* ESLint Plugin: Rename avoid-unguarded-get-range-at to no-unguarded-get-range-at
  • Loading branch information
bor0 authored and aduth committed Jul 29, 2019
1 parent fcbdd20 commit d45c8ea
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 1 deletion.
3 changes: 2 additions & 1 deletion packages/components/src/autocomplete/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,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 );
Expand Down
1 change: 1 addition & 0 deletions packages/eslint-plugin/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
### New Features

- [`@wordpress/no-unused-vars-before-return`](https://github.com/WordPress/gutenberg/blob/master/packages/eslint-plugin/docs/rules/no-unused-vars-before-return.md) now supports an `excludePattern` option to exempt function calls by name.
- 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)

### Improvements

Expand Down
1 change: 1 addition & 0 deletions packages/eslint-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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|✓
[no-unguarded-get-range-at](/packages/eslint-plugin/docs/rules/no-unguarded-get-range-at.md)| Disallow the usage of unguarded `getRangeAt` calls|✓

### Legacy

Expand Down
1 change: 1 addition & 0 deletions packages/eslint-plugin/configs/custom.js
Original file line number Diff line number Diff line change
Expand Up @@ -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/no-unguarded-get-range-at': 'error',
'no-restricted-syntax': [
'error',
{
Expand Down
18 changes: 18 additions & 0 deletions packages/eslint-plugin/docs/rules/no-unguarded-get-range-at.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# 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.

## 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;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* External dependencies
*/
import { RuleTester } from 'eslint';

/**
* Internal dependencies
*/
import rule from '../no-unguarded-get-range-at';

const ruleTester = new RuleTester( {
parserOptions: {
ecmaVersion: 6,
},
} );

ruleTester.run( 'no-unguarded-get-range-at', 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' } ],
},
],
} );
16 changes: 16 additions & 0 deletions packages/eslint-plugin/rules/no-unguarded-get-range-at.js
Original file line number Diff line number Diff line change
@@ -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',
} );
},
};
},
};

0 comments on commit d45c8ea

Please sign in to comment.