@blumintinc/eslint-plugin-blumint 1.20.37 → 1.20.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.js +1 -1
- package/lib/rules/enforce-callback-memo.js +42 -11
- package/package.json +1 -1
- package/release-manifest.json +14 -0
package/lib/index.js
CHANGED
|
@@ -22,21 +22,48 @@ exports.default = (0, createRule_1.createRule)({
|
|
|
22
22
|
return (node.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
|
|
23
23
|
node.type === utils_1.AST_NODE_TYPES.FunctionExpression);
|
|
24
24
|
}
|
|
25
|
+
// Matches both the bare hook (`useMemo(...)`, including the generic form
|
|
26
|
+
// `useCallback<T>(...)`, whose callee is still an identifier) and the
|
|
27
|
+
// namespaced form (`React.useMemo(...)`).
|
|
28
|
+
function isHookCallee(callee, hookName) {
|
|
29
|
+
if (callee.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
30
|
+
return callee.name === hookName;
|
|
31
|
+
}
|
|
32
|
+
return (callee.type === utils_1.AST_NODE_TYPES.MemberExpression &&
|
|
33
|
+
!callee.computed &&
|
|
34
|
+
callee.property.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
35
|
+
callee.property.name === hookName);
|
|
36
|
+
}
|
|
25
37
|
function isInsideUseCallback(node) {
|
|
26
38
|
let current = node.parent;
|
|
27
39
|
while (current) {
|
|
28
|
-
if (current.type === utils_1.AST_NODE_TYPES.CallExpression
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
40
|
+
if (current.type === utils_1.AST_NODE_TYPES.CallExpression &&
|
|
41
|
+
isHookCallee(current.callee, 'useCallback')) {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
current = current.parent;
|
|
45
|
+
}
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
// A `useMemo` factory re-runs only when its dependencies change, so every
|
|
49
|
+
// value it produces — including JSX and the inline handlers nested in that
|
|
50
|
+
// JSX — is exactly as referentially stable as the memo itself. Demanding an
|
|
51
|
+
// extra `useCallback` there buys nothing.
|
|
52
|
+
//
|
|
53
|
+
// `useCallback` deliberately gets no such treatment: it memoizes a function
|
|
54
|
+
// that runs on every invocation, so the JSX it returns (and the inline
|
|
55
|
+
// functions in it) is rebuilt each call and stays worth reporting.
|
|
56
|
+
function isInsideUseMemoFactory(node) {
|
|
57
|
+
let child = node;
|
|
58
|
+
let current = node.parent;
|
|
59
|
+
while (current) {
|
|
60
|
+
if (current.type === utils_1.AST_NODE_TYPES.CallExpression &&
|
|
61
|
+
isHookCallee(current.callee, 'useMemo') &&
|
|
62
|
+
// Only the factory argument is memoized; the dependency array is not.
|
|
63
|
+
current.arguments[0] === child) {
|
|
64
|
+
return true;
|
|
39
65
|
}
|
|
66
|
+
child = current;
|
|
40
67
|
current = current.parent;
|
|
41
68
|
}
|
|
42
69
|
return false;
|
|
@@ -167,6 +194,10 @@ exports.default = (0, createRule_1.createRule)({
|
|
|
167
194
|
node.value.type !== utils_1.AST_NODE_TYPES.JSXExpressionContainer) {
|
|
168
195
|
return;
|
|
169
196
|
}
|
|
197
|
+
// Props of JSX built inside a useMemo factory inherit the memo's stability
|
|
198
|
+
if (isInsideUseMemoFactory(node)) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
170
201
|
const { expression } = node.value;
|
|
171
202
|
// Skip if the prop is already wrapped in useCallback or useMemo
|
|
172
203
|
if (expression.type === utils_1.AST_NODE_TYPES.CallExpression &&
|
package/package.json
CHANGED
package/release-manifest.json
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "1.20.38",
|
|
4
|
+
"date": "2026-07-30T20:52:16.921Z",
|
|
5
|
+
"rules": [
|
|
6
|
+
{
|
|
7
|
+
"name": "enforce-callback-memo",
|
|
8
|
+
"changeType": "fix",
|
|
9
|
+
"issues": [
|
|
10
|
+
1465
|
|
11
|
+
],
|
|
12
|
+
"summary": "allow an inline callback inside a useMemo factory (closes #1465)"
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
},
|
|
2
16
|
{
|
|
3
17
|
"version": "1.20.37",
|
|
4
18
|
"date": "2026-07-30T18:07:02.175Z",
|