Skip to content

Commit

Permalink
New rule: no-nodelist-unsupported-methods
Browse files Browse the repository at this point in the history
This rule disallows NodeList prototype methods unsupported by various browsers.
  • Loading branch information
edg2s committed May 11, 2022
1 parent 6c93a03 commit 17b4243
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 0 deletions.
32 changes: 32 additions & 0 deletions docs/rules/no-nodelist-unsupported-methods.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[//]: # (This file is generated by eslint-docgen. Do not edit it directly.)

# no-nodelist-unsupported-methods

Prohibits [NodeList methods](https://developer.mozilla.org/en-US/docs/Web/API/NodeList#browser_compatibility) not supported by Chrome<51, Firefox<50, Safari<10, IE & others

## Rule details

❌ Examples of **incorrect** code:
```js
element.childNodes.forEach();
element.childNodes.entries();
element.childNodes.keys();
element.childNodes.values();
document.querySelectorAll( '.foo' ).forEach();
```

✔️ Examples of **correct** code:
```js
Array.prototype.forEach.call( element.childNodes, function ( element ) {} );
[].forEach();
[].property.forEach();
[].method().forEach();
element.childNodes.item( 1 );
document.querySelectorAll( '.foo' ).item( 1 );
forEach();
```

## Resources

* [Rule source](/src/rules/no-nodelist-unsupported-methods.js)
* [Test source](/tests/rules/no-nodelist-unsupported-methods.js)
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module.exports = {
'class-doc': require( './rules/class-doc.js' ),
'msg-doc': require( './rules/msg-doc.js' ),
'no-extended-unicode-identifiers': require( './rules/no-extended-unicode-identifiers' ),
'no-nodelist-unsupported-methods': require( './rules/no-nodelist-unsupported-methods' ),
'no-vue-dynamic-i18n': require( './rules/no-vue-dynamic-i18n.js' ),
'valid-package-file-require': require( './rules/valid-package-file-require.js' ),
'vue-exports-component-directive': require( './rules/vue-exports-component-directive.js' )
Expand Down
49 changes: 49 additions & 0 deletions src/rules/no-nodelist-unsupported-methods.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
'use strict';

const methods = [ 'forEach', 'entries', 'keys', 'values' ];

module.exports = {
meta: {
type: 'problem',
docs: {
// Full browser support table: https://developer.mozilla.org/en-US/docs/Web/API/NodeList#browser_compatibility
description: 'Prohibits [NodeList methods](https://developer.mozilla.org/en-US/docs/Web/API/NodeList#browser_compatibility) not supported by Chrome<51, Firefox<50, Safari<10, IE & others'
},
schema: [],
messages: {
nodelistMethod: 'NodeList.{{method}} not supported by Chrome<51, Firefox<50, Safari<10, IE & others. Use Array.prototype.{{method}}.call instead.'
}
},

create( context ) {
return {
CallExpression( node ) {
if ( node.callee.type !== 'MemberExpression' ) {
return;
}
const name = node.callee.property.name;
if ( !methods.includes( name ) ) {
return;
}

if (
// element.childNodes.forEach
( node.callee.object.property && node.callee.object.property.name === 'childNodes' ) ||
// element.querySelectorAll( '' ).forEach
(
node.callee.object.callee && node.callee.object.callee.property &&
node.callee.object.callee.property.name === 'querySelectorAll'
)
) {
context.report( {
node: node,
messageId: 'nodelistMethod',
data: {
method: name
}
} );
}
}
};
}
};
42 changes: 42 additions & 0 deletions tests/rules/no-nodelist-unsupported-methods.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
'use strict';

const rule = require( '../../src/rules/no-nodelist-unsupported-methods' );
const RuleTester = require( 'eslint-docgen' ).RuleTester;
const errorMessage = function ( method ) {
return `NodeList.${method} not supported by Chrome<51, Firefox<50, Safari<10, IE & others. Use Array.prototype.${method}.call instead.`;
};

const ruleTester = new RuleTester();
ruleTester.run( 'no-nodelist-unsupported-methods', rule, {
valid: [
'Array.prototype.forEach.call( element.childNodes, function ( element ) {} )',
'[].forEach()',
'[].property.forEach()',
'[].method().forEach()',
'element.childNodes.item(1)',
'document.querySelectorAll(".foo").item(1)',
'forEach()'
],
invalid: [
{
code: 'element.childNodes.forEach()',
errors: [ errorMessage( 'forEach' ) ]
},
{
code: 'element.childNodes.entries()',
errors: [ errorMessage( 'entries' ) ]
},
{
code: 'element.childNodes.keys()',
errors: [ errorMessage( 'keys' ) ]
},
{
code: 'element.childNodes.values()',
errors: [ errorMessage( 'values' ) ]
},
{
code: 'document.querySelectorAll(".foo").forEach()',
errors: [ errorMessage( 'forEach' ) ]
}
]
} );

0 comments on commit 17b4243

Please sign in to comment.