Skip to content

Commit 947a949

Browse files
committed
meta: add no-unsafe-array-iteration.js rule
1 parent eabb75c commit 947a949

2 files changed

Lines changed: 68 additions & 0 deletions

File tree

lib/eslint.config_partial.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@ export default [
388388
'node-core/lowercase-name-for-primitive': 'error',
389389
'node-core/non-ascii-character': 'error',
390390
'node-core/no-array-destructuring': 'error',
391+
'node-core/no-unsafe-array-iteration': 'error',
391392
'node-core/prefer-primordials': [
392393
'error',
393394
{ name: 'AggregateError' },
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/**
2+
* @file Rule to prevent unsafe array iteration patterns like for...of loops
3+
* which rely on user-mutable global methods (Array.prototype[Symbol.iterator]).
4+
* Instead, traditional for loops should be used for safer iteration.
5+
*/
6+
'use strict';
7+
8+
//------------------------------------------------------------------------------
9+
// Rule Definition
10+
//------------------------------------------------------------------------------
11+
12+
const USE_FOR_LOOP = 'Use traditional for loop instead of for...of for array iteration to avoid relying on user-mutable Symbol.iterator.';
13+
14+
/**
15+
* Checks if a node represents an array-like expression
16+
* @param {Object} node - The AST node to check
17+
* @returns {boolean} - True if the node appears to be an array
18+
*/
19+
function isArrayLike(node) {
20+
// Direct array literals
21+
if (node.type === 'ArrayExpression') {
22+
return true;
23+
}
24+
25+
// Variables/identifiers that might be arrays (we'll be conservative and flag all)
26+
if (node.type === 'Identifier') {
27+
return true;
28+
}
29+
30+
// Member expressions like obj.array, obj['array']
31+
if (node.type === 'MemberExpression') {
32+
return true;
33+
}
34+
35+
// Call expressions that might return arrays
36+
if (node.type === 'CallExpression') {
37+
return true;
38+
}
39+
40+
return false;
41+
}
42+
43+
module.exports = {
44+
meta: {
45+
type: 'problem',
46+
docs: {
47+
description: 'disallow for...of loops on arrays to prevent unsafe iteration',
48+
category: 'Possible Errors',
49+
},
50+
fixable: null, // Not auto-fixable due to complexity of conversion
51+
schema: [],
52+
},
53+
54+
create(context) {
55+
return {
56+
ForOfStatement(node) {
57+
// Check if we're iterating over something that looks like an array
58+
if (isArrayLike(node.right)) {
59+
context.report({
60+
node,
61+
message: USE_FOR_LOOP,
62+
});
63+
}
64+
},
65+
};
66+
},
67+
};

0 commit comments

Comments
 (0)