mirror of
https://github.com/nodejs/node.git
synced 2024-11-21 10:59:27 +00:00
26288ff25e
Iterating over arrays should be avoided because it relies on user-mutable global methods (`Array.prototype[Symbol.iterator]` and `%ArrayIteratorPrototype%.next`), we should instead use other alternatives. This commit adds a rule that disallow array destructuring syntax in favor of object destructuring syntax. Note that you can ignore this rule if you are using the array destructuring syntax over a safe iterable, or actually want to iterate over a user-provided object. PR-URL: https://github.com/nodejs/node/pull/36818 Reviewed-By: Rich Trott <rtrott@gmail.com>
84 lines
2.7 KiB
JavaScript
84 lines
2.7 KiB
JavaScript
/**
|
|
* @fileoverview Iterating over arrays should be avoided because it relies on
|
|
* user-mutable global methods (`Array.prototype[Symbol.iterator]`
|
|
* and `%ArrayIteratorPrototype%.next`), we should instead use
|
|
* other alternatives. This file defines a rule that disallow
|
|
* array destructuring syntax in favor of object destructuring
|
|
* syntax. Note that you can ignore this rule if you are using
|
|
* the array destructuring syntax over a safe iterable, or
|
|
* actually want to iterate over a user-provided object.
|
|
* @author aduh95 <duhamelantoine1995@gmail.com>
|
|
*/
|
|
'use strict';
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Rule Definition
|
|
//------------------------------------------------------------------------------
|
|
|
|
const USE_OBJ_DESTRUCTURING =
|
|
'Use object destructuring instead of array destructuring.';
|
|
const USE_ARRAY_METHODS =
|
|
'Use primordials.ArrayPrototypeSlice to avoid unsafe array iteration.';
|
|
|
|
const findComma = (sourceCode, elements, i, start) => {
|
|
if (i === 0)
|
|
return sourceCode.getTokenAfter(sourceCode.getTokenByRangeStart(start));
|
|
|
|
let element;
|
|
const originalIndex = i;
|
|
while (i && !element) {
|
|
element = elements[--i];
|
|
}
|
|
let token = sourceCode.getTokenAfter(
|
|
element ?? sourceCode.getTokenByRangeStart(start)
|
|
);
|
|
for (; i < originalIndex; i++) {
|
|
token = sourceCode.getTokenAfter(token);
|
|
}
|
|
return token;
|
|
};
|
|
const createFix = (fixer, sourceCode, { range: [start, end], elements }) => [
|
|
fixer.replaceTextRange([start, start + 1], '{'),
|
|
fixer.replaceTextRange([end - 1, end], '}'),
|
|
...elements.map((node, i) =>
|
|
(node === null ?
|
|
fixer.remove(findComma(sourceCode, elements, i, start)) :
|
|
fixer.insertTextBefore(node, i + ':'))
|
|
),
|
|
];
|
|
const arrayPatternContainsRestOperator = ({ elements }) =>
|
|
elements?.find((node) => node?.type === 'RestElement');
|
|
|
|
module.exports = {
|
|
meta: {
|
|
type: 'suggestion',
|
|
fixable: 'code',
|
|
schema: [],
|
|
},
|
|
create(context) {
|
|
const sourceCode = context.getSourceCode();
|
|
|
|
return {
|
|
ArrayPattern(node) {
|
|
const hasRest = arrayPatternContainsRestOperator(node);
|
|
context.report({
|
|
message: hasRest ? USE_ARRAY_METHODS : USE_OBJ_DESTRUCTURING,
|
|
node: hasRest || node,
|
|
fix: hasRest ?
|
|
undefined :
|
|
(fixer) => [
|
|
...(node.parent.type === 'AssignmentExpression' ?
|
|
[
|
|
fixer.insertTextBefore(node.parent, '('),
|
|
fixer.insertTextAfter(node.parent, ')'),
|
|
] :
|
|
[]),
|
|
...createFix(fixer, sourceCode, node),
|
|
],
|
|
});
|
|
|
|
},
|
|
};
|
|
},
|
|
};
|