eslint-plugin-react-hooks 1.5.1 → 1.6.0
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.
|
@@ -760,7 +760,7 @@ var ExhaustiveDeps = {
|
|
|
760
760
|
// So no need to check for dependency inclusion.
|
|
761
761
|
var depsIndex = callbackIndex + 1;
|
|
762
762
|
var declaredDependenciesNode = node.parent.arguments[depsIndex];
|
|
763
|
-
if (!declaredDependenciesNode) {
|
|
763
|
+
if (!declaredDependenciesNode && !isEffect) {
|
|
764
764
|
// These are only used for optimization.
|
|
765
765
|
if (reactiveHookName === 'useMemo' || reactiveHookName === 'useCallback') {
|
|
766
766
|
// TODO: Can this have an autofix?
|
|
@@ -775,7 +775,7 @@ var ExhaustiveDeps = {
|
|
|
775
775
|
if (isEffect && node.async) {
|
|
776
776
|
context.report({
|
|
777
777
|
node: node,
|
|
778
|
-
message: 'Effect callbacks are synchronous to prevent race conditions. ' + 'Put the async function inside:\n\n' + 'useEffect(() => {\n' + '
|
|
778
|
+
message: 'Effect callbacks are synchronous to prevent race conditions. ' + 'Put the async function inside:\n\n' + 'useEffect(() => {\n' + ' async function fetchData() {\n' + ' // You can await here\n' + ' const response = await MyAPI.getData(someId);\n' + ' // ...\n' + ' }\n' + ' fetchData();\n' + '}, [someId]); // Or [] if effect doesn\'t need props or state\n\n' + 'Learn more about data fetching with Hooks: https://fb.me/react-hooks-data-fetching'
|
|
779
779
|
});
|
|
780
780
|
}
|
|
781
781
|
|
|
@@ -1022,6 +1022,12 @@ var ExhaustiveDeps = {
|
|
|
1022
1022
|
});
|
|
1023
1023
|
}
|
|
1024
1024
|
|
|
1025
|
+
// Ignore references to the function itself as it's not defined yet.
|
|
1026
|
+
var def = reference.resolved.defs[0];
|
|
1027
|
+
if (def != null && def.node != null && def.node.init === node.parent) {
|
|
1028
|
+
continue;
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1025
1031
|
// Add the dependency to a map so we can make sure it is referenced
|
|
1026
1032
|
// again in our dependencies array. Remember whether it's static.
|
|
1027
1033
|
if (!dependencies.has(dependency)) {
|
|
@@ -1108,6 +1114,95 @@ var ExhaustiveDeps = {
|
|
|
1108
1114
|
});
|
|
1109
1115
|
});
|
|
1110
1116
|
|
|
1117
|
+
// Warn about assigning to variables in the outer scope.
|
|
1118
|
+
// Those are usually bugs.
|
|
1119
|
+
var staleAssignments = new Set();
|
|
1120
|
+
function reportStaleAssignment(writeExpr, key) {
|
|
1121
|
+
if (staleAssignments.has(key)) {
|
|
1122
|
+
return;
|
|
1123
|
+
}
|
|
1124
|
+
staleAssignments.add(key);
|
|
1125
|
+
context.report({
|
|
1126
|
+
node: writeExpr,
|
|
1127
|
+
message: 'Assignments to the \'' + key + '\' variable from inside React Hook ' + (context.getSource(reactiveHook) + ' will be lost after each ') + 'render. To preserve the value over time, store it in a useRef ' + 'Hook and keep the mutable value in the \'.current\' property. ' + 'Otherwise, you can move this variable directly inside ' + (context.getSource(reactiveHook) + '.')
|
|
1128
|
+
});
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
// Remember which deps are optional and report bad usage first.
|
|
1132
|
+
var optionalDependencies = new Set();
|
|
1133
|
+
dependencies.forEach(function (_ref2, key) {
|
|
1134
|
+
var isStatic = _ref2.isStatic,
|
|
1135
|
+
references = _ref2.references;
|
|
1136
|
+
|
|
1137
|
+
if (isStatic) {
|
|
1138
|
+
optionalDependencies.add(key);
|
|
1139
|
+
}
|
|
1140
|
+
references.forEach(function (reference) {
|
|
1141
|
+
if (reference.writeExpr) {
|
|
1142
|
+
reportStaleAssignment(reference.writeExpr, key);
|
|
1143
|
+
}
|
|
1144
|
+
});
|
|
1145
|
+
});
|
|
1146
|
+
|
|
1147
|
+
if (staleAssignments.size > 0) {
|
|
1148
|
+
// The intent isn't clear so we'll wait until you fix those first.
|
|
1149
|
+
return;
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
if (!declaredDependenciesNode) {
|
|
1153
|
+
// Check if there are any top-level setState() calls.
|
|
1154
|
+
// Those tend to lead to infinite loops.
|
|
1155
|
+
var setStateInsideEffectWithoutDeps = null;
|
|
1156
|
+
dependencies.forEach(function (_ref3, key) {
|
|
1157
|
+
var isStatic = _ref3.isStatic,
|
|
1158
|
+
references = _ref3.references;
|
|
1159
|
+
|
|
1160
|
+
if (setStateInsideEffectWithoutDeps) {
|
|
1161
|
+
return;
|
|
1162
|
+
}
|
|
1163
|
+
references.forEach(function (reference) {
|
|
1164
|
+
if (setStateInsideEffectWithoutDeps) {
|
|
1165
|
+
return;
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
var id = reference.identifier;
|
|
1169
|
+
var isSetState = setStateCallSites.has(id);
|
|
1170
|
+
if (!isSetState) {
|
|
1171
|
+
return;
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
var fnScope = reference.from;
|
|
1175
|
+
while (fnScope.type !== 'function') {
|
|
1176
|
+
fnScope = fnScope.upper;
|
|
1177
|
+
}
|
|
1178
|
+
var isDirectlyInsideEffect = fnScope.block === node;
|
|
1179
|
+
if (isDirectlyInsideEffect) {
|
|
1180
|
+
// TODO: we could potentially ignore early returns.
|
|
1181
|
+
setStateInsideEffectWithoutDeps = key;
|
|
1182
|
+
}
|
|
1183
|
+
});
|
|
1184
|
+
});
|
|
1185
|
+
if (setStateInsideEffectWithoutDeps) {
|
|
1186
|
+
var _collectRecommendatio = collectRecommendations({
|
|
1187
|
+
dependencies: dependencies,
|
|
1188
|
+
declaredDependencies: [],
|
|
1189
|
+
optionalDependencies: optionalDependencies,
|
|
1190
|
+
externalDependencies: new Set(),
|
|
1191
|
+
isEffect: true
|
|
1192
|
+
}),
|
|
1193
|
+
_suggestedDependencies = _collectRecommendatio.suggestedDependencies;
|
|
1194
|
+
|
|
1195
|
+
context.report({
|
|
1196
|
+
node: node.parent.callee,
|
|
1197
|
+
message: 'React Hook ' + reactiveHookName + ' contains a call to \'' + setStateInsideEffectWithoutDeps + '\'. ' + 'Without a list of dependencies, this can lead to an infinite chain of updates. ' + 'To fix this, pass [' + _suggestedDependencies.join(', ') + ('] as a second argument to the ' + reactiveHookName + ' Hook.'),
|
|
1198
|
+
fix: function (fixer) {
|
|
1199
|
+
return fixer.insertTextAfter(node, ', [' + _suggestedDependencies.join(', ') + ']');
|
|
1200
|
+
}
|
|
1201
|
+
});
|
|
1202
|
+
}
|
|
1203
|
+
return;
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1111
1206
|
var declaredDependencies = [];
|
|
1112
1207
|
var externalDependencies = new Set();
|
|
1113
1208
|
if (declaredDependenciesNode.type !== 'ArrayExpression') {
|
|
@@ -1184,51 +1279,17 @@ var ExhaustiveDeps = {
|
|
|
1184
1279
|
});
|
|
1185
1280
|
}
|
|
1186
1281
|
|
|
1187
|
-
|
|
1188
|
-
// Those are usually bugs.
|
|
1189
|
-
var staleAssignments = new Set();
|
|
1190
|
-
function reportStaleAssignment(writeExpr, key) {
|
|
1191
|
-
if (staleAssignments.has(key)) {
|
|
1192
|
-
return;
|
|
1193
|
-
}
|
|
1194
|
-
staleAssignments.add(key);
|
|
1195
|
-
context.report({
|
|
1196
|
-
node: writeExpr,
|
|
1197
|
-
message: 'Assignments to the \'' + key + '\' variable from inside React Hook ' + (context.getSource(reactiveHook) + ' will be lost after each ') + 'render. To preserve the value over time, store it in a useRef ' + 'Hook and keep the mutable value in the \'.current\' property. ' + 'Otherwise, you can move this variable directly inside ' + (context.getSource(reactiveHook) + '.')
|
|
1198
|
-
});
|
|
1199
|
-
}
|
|
1200
|
-
|
|
1201
|
-
// Remember which deps are optional and report bad usage first.
|
|
1202
|
-
var optionalDependencies = new Set();
|
|
1203
|
-
dependencies.forEach(function (_ref2, key) {
|
|
1204
|
-
var isStatic = _ref2.isStatic,
|
|
1205
|
-
references = _ref2.references;
|
|
1206
|
-
|
|
1207
|
-
if (isStatic) {
|
|
1208
|
-
optionalDependencies.add(key);
|
|
1209
|
-
}
|
|
1210
|
-
references.forEach(function (reference) {
|
|
1211
|
-
if (reference.writeExpr) {
|
|
1212
|
-
reportStaleAssignment(reference.writeExpr, key);
|
|
1213
|
-
}
|
|
1214
|
-
});
|
|
1215
|
-
});
|
|
1216
|
-
if (staleAssignments.size > 0) {
|
|
1217
|
-
// The intent isn't clear so we'll wait until you fix those first.
|
|
1218
|
-
return;
|
|
1219
|
-
}
|
|
1220
|
-
|
|
1221
|
-
var _collectRecommendatio = collectRecommendations({
|
|
1282
|
+
var _collectRecommendatio2 = collectRecommendations({
|
|
1222
1283
|
dependencies: dependencies,
|
|
1223
1284
|
declaredDependencies: declaredDependencies,
|
|
1224
1285
|
optionalDependencies: optionalDependencies,
|
|
1225
1286
|
externalDependencies: externalDependencies,
|
|
1226
1287
|
isEffect: isEffect
|
|
1227
1288
|
}),
|
|
1228
|
-
suggestedDependencies =
|
|
1229
|
-
unnecessaryDependencies =
|
|
1230
|
-
missingDependencies =
|
|
1231
|
-
duplicateDependencies =
|
|
1289
|
+
suggestedDependencies = _collectRecommendatio2.suggestedDependencies,
|
|
1290
|
+
unnecessaryDependencies = _collectRecommendatio2.unnecessaryDependencies,
|
|
1291
|
+
missingDependencies = _collectRecommendatio2.missingDependencies,
|
|
1292
|
+
duplicateDependencies = _collectRecommendatio2.duplicateDependencies;
|
|
1232
1293
|
|
|
1233
1294
|
var problemCount = duplicateDependencies.size + missingDependencies.size + unnecessaryDependencies.size;
|
|
1234
1295
|
|
|
@@ -1241,9 +1302,9 @@ var ExhaustiveDeps = {
|
|
|
1241
1302
|
componentScope: componentScope,
|
|
1242
1303
|
scope: scope
|
|
1243
1304
|
});
|
|
1244
|
-
bareFunctions.forEach(function (
|
|
1245
|
-
var fn =
|
|
1246
|
-
suggestUseCallback =
|
|
1305
|
+
bareFunctions.forEach(function (_ref4) {
|
|
1306
|
+
var fn = _ref4.fn,
|
|
1307
|
+
suggestUseCallback = _ref4.suggestUseCallback;
|
|
1247
1308
|
|
|
1248
1309
|
var message = 'The \'' + fn.name.name + '\' function makes the dependencies of ' + (reactiveHookName + ' Hook (at line ' + declaredDependenciesNode.loc.start.line + ') ') + 'change on every render.';
|
|
1249
1310
|
if (suggestUseCallback) {
|
|
@@ -1506,12 +1567,12 @@ var ExhaustiveDeps = {
|
|
|
1506
1567
|
};
|
|
1507
1568
|
|
|
1508
1569
|
// The meat of the logic.
|
|
1509
|
-
function collectRecommendations(
|
|
1510
|
-
var dependencies =
|
|
1511
|
-
declaredDependencies =
|
|
1512
|
-
optionalDependencies =
|
|
1513
|
-
externalDependencies =
|
|
1514
|
-
isEffect =
|
|
1570
|
+
function collectRecommendations(_ref5) {
|
|
1571
|
+
var dependencies = _ref5.dependencies,
|
|
1572
|
+
declaredDependencies = _ref5.declaredDependencies,
|
|
1573
|
+
optionalDependencies = _ref5.optionalDependencies,
|
|
1574
|
+
externalDependencies = _ref5.externalDependencies,
|
|
1575
|
+
isEffect = _ref5.isEffect;
|
|
1515
1576
|
|
|
1516
1577
|
// Our primary data structure.
|
|
1517
1578
|
// It is a logical representation of property chains:
|
|
@@ -1544,8 +1605,8 @@ function collectRecommendations(_ref4) {
|
|
|
1544
1605
|
|
|
1545
1606
|
// Mark all satisfied nodes.
|
|
1546
1607
|
// Imagine checkmarks next to each declared dependency.
|
|
1547
|
-
declaredDependencies.forEach(function (
|
|
1548
|
-
var key =
|
|
1608
|
+
declaredDependencies.forEach(function (_ref6) {
|
|
1609
|
+
var key = _ref6.key;
|
|
1549
1610
|
|
|
1550
1611
|
var node = getOrCreateNodeByPath(depTree, key);
|
|
1551
1612
|
node.isSatisfiedRecursively = true;
|
|
@@ -1661,8 +1722,8 @@ function collectRecommendations(_ref4) {
|
|
|
1661
1722
|
var suggestedDependencies = [];
|
|
1662
1723
|
var unnecessaryDependencies = new Set();
|
|
1663
1724
|
var duplicateDependencies = new Set();
|
|
1664
|
-
declaredDependencies.forEach(function (
|
|
1665
|
-
var key =
|
|
1725
|
+
declaredDependencies.forEach(function (_ref7) {
|
|
1726
|
+
var key = _ref7.key;
|
|
1666
1727
|
|
|
1667
1728
|
// Does this declared dep satsify a real need?
|
|
1668
1729
|
if (satisfyingDependencies.has(key)) {
|
|
@@ -1704,14 +1765,14 @@ function collectRecommendations(_ref4) {
|
|
|
1704
1765
|
|
|
1705
1766
|
// Finds functions declared as dependencies
|
|
1706
1767
|
// that would invalidate on every render.
|
|
1707
|
-
function scanForDeclaredBareFunctions(
|
|
1708
|
-
var declaredDependencies =
|
|
1709
|
-
declaredDependenciesNode =
|
|
1710
|
-
componentScope =
|
|
1711
|
-
scope =
|
|
1712
|
-
|
|
1713
|
-
var bareFunctions = declaredDependencies.map(function (
|
|
1714
|
-
var key =
|
|
1768
|
+
function scanForDeclaredBareFunctions(_ref8) {
|
|
1769
|
+
var declaredDependencies = _ref8.declaredDependencies,
|
|
1770
|
+
declaredDependenciesNode = _ref8.declaredDependenciesNode,
|
|
1771
|
+
componentScope = _ref8.componentScope,
|
|
1772
|
+
scope = _ref8.scope;
|
|
1773
|
+
|
|
1774
|
+
var bareFunctions = declaredDependencies.map(function (_ref9) {
|
|
1775
|
+
var key = _ref9.key;
|
|
1715
1776
|
|
|
1716
1777
|
var fnRef = componentScope.set.get(key);
|
|
1717
1778
|
if (fnRef == null) {
|
|
@@ -7,41 +7,45 @@
|
|
|
7
7
|
* LICENSE file in the root directory of this source tree.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
'use strict';function
|
|
11
|
-
function
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
!0
|
|
15
|
-
function
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
function
|
|
19
|
-
function
|
|
20
|
-
function
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
h=!0
|
|
27
|
-
|
|
28
|
-
a.report({node:
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
(
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
(a.getSource(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
("
|
|
44
|
-
0<
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
10
|
+
'use strict';function R(a){return"Identifier"===a.type?/^use[A-Z0-9].*$/.test(a.name):"MemberExpression"===a.type&&!a.computed&&R(a.property)?(a=a.object,"Identifier"===a.type&&"React"===a.name):!1}function aa(a){return"Identifier"===a.type?!/^[a-z]/.test(a.name):!1}function ba(a){for(;a;){var b=ca(a);if(b&&(aa(b)||R(b)))return!0;a=a.parent}return!1}
|
|
11
|
+
function ca(a){if("FunctionDeclaration"===a.type||"FunctionExpression"===a.type&&a.id)return a.id;if("FunctionExpression"===a.type||"ArrowFunctionExpression"===a.type)return"VariableDeclarator"===a.parent.type&&a.parent.init===a?a.parent.id:"AssignmentExpression"===a.parent.type&&a.parent.right===a&&"="===a.parent.operator?a.parent.left:"Property"!==a.parent.type||a.parent.value!==a||a.parent.computed?"AssignmentPattern"!==a.parent.type||a.parent.right!==a||a.parent.computed?void 0:a.parent.left:
|
|
12
|
+
a.parent.key}
|
|
13
|
+
function V(a){function b(){return{isRequired:!1,isSatisfiedRecursively:!1,hasRequiredNodesBelow:!1,children:new Map}}function e(a,h){h=h.split(".");var l=!0,c=!1,e=void 0;try{for(var f=h[Symbol.iterator](),p;!(l=(p=f.next()).done);l=!0){var u=p.value,g=a.children.get(u);g||(g=b(),a.children.set(u,g));a=g}}catch(E){c=!0,e=E}finally{try{!l&&f.return&&f.return()}finally{if(c)throw e;}}return a}function f(a,h,c){h=h.split(".");var l=!0,b=!1,f=void 0;try{for(var e=h[Symbol.iterator](),g;!(l=(g=e.next()).done);l=
|
|
14
|
+
!0){var u=a.children.get(g.value);if(!u)break;c(u);a=u}}catch(E){b=!0,f=E}finally{try{!l&&e.return&&e.return()}finally{if(b)throw f;}}}function h(a,c,b,e){a.children.forEach(function(a,l){var f=e(l);a.isSatisfiedRecursively?a.hasRequiredNodesBelow&&b.add(f):a.isRequired?c.add(f):h(a,c,b,function(a){return f+"."+a})})}var u=a.dependencies,q=a.declaredDependencies,t=a.optionalDependencies,c=a.externalDependencies,n=a.isEffect,C=b();u.forEach(function(a,h){e(C,h).isRequired=!0;f(C,h,function(a){a.hasRequiredNodesBelow=
|
|
15
|
+
!0})});q.forEach(function(a){e(C,a.key).isSatisfiedRecursively=!0});t.forEach(function(a){e(C,a).isSatisfiedRecursively=!0});a=new Set;var g=new Set;h(C,a,g,function(a){return a});var v=[],A=new Set,B=new Set;q.forEach(function(a){a=a.key;g.has(a)?-1===v.indexOf(a)?v.push(a):B.add(a):!n||a.endsWith(".current")||c.has(a)?A.add(a):-1===v.indexOf(a)&&v.push(a)});a.forEach(function(a){v.push(a)});return{suggestedDependencies:v,unnecessaryDependencies:A,duplicateDependencies:B,missingDependencies:a}}
|
|
16
|
+
function da(a){var b=a.declaredDependenciesNode,e=a.componentScope,f=a.scope;return a.declaredDependencies.map(function(a){a=e.set.get(a.key);if(null==a)return null;var b=a.defs[0];return null==b?null:"Variable"===b.type&&"VariableDeclarator"===b.node.type&&null!=b.node.init&&("ArrowFunctionExpression"===b.node.init.type||"FunctionExpression"===b.node.init.type)||"FunctionName"===b.type&&"FunctionDeclaration"===b.node.type?a:null}).filter(Boolean).map(function(a){var e=a.defs[0];a:{for(var h=!1,t=
|
|
17
|
+
0;t<a.references.length;t++){var c=a.references[t];if(c.writeExpr)if(h){a=!0;break a}else{h=!0;continue}for(var n=c.from;n!==f&&null!=n;)n=n.upper;if(n!==f&&!ea(b,c.identifier)){a=!0;break a}}a=!1}return{fn:e,suggestUseCallback:a}})}function fa(a){return"MemberExpression"!==a.parent.type||a.parent.object!==a||"current"===a.parent.property.name||a.parent.computed||null!=a.parent.parent&&"CallExpression"===a.parent.parent.type&&a.parent.parent.callee===a.parent?a:fa(a.parent)}
|
|
18
|
+
function X(a){if("Identifier"===a.type)return a.name;if("MemberExpression"!==a.type||a.computed)throw Error("Unsupported node type: "+a.type);var b=X(a.object);a=X(a.property);return b+"."+a}function ja(a){return"MemberExpression"!==a.type||"Identifier"!==a.object.type||"React"!==a.object.name||"Identifier"!==a.property.type||a.computed?a:a.property}
|
|
19
|
+
function ka(a,b){var e=ja(a);if("Identifier"!==e.type)return null;switch(e.name){case "useEffect":case "useLayoutEffect":case "useCallback":case "useMemo":return 0;case "useImperativeHandle":return 1;default:if(e===a&&b&&b.additionalHooks){a=void 0;try{a=X(e)}catch(f){if(/Unsupported node type/.test(f.message))return 0;throw f;}return b.additionalHooks.test(a)?0:-1}return-1}}
|
|
20
|
+
function Y(a,b){for(var e=[a],f=null;e.length;){f=e.shift();if("Identifier"===f.type&&f.name===b.name&&f.range[0]===b.range[0]&&f.range[1]===b.range[1])return f;if(ea(f,b)){a=!0;var h=!1,u=void 0;try{for(var q=Object.entries(f)[Symbol.iterator](),t;!(a=(t=q.next()).done);a=!0){var c=t.value,n=c[1];"parent"!==c[0]&&(la(n)?(n.parent=f,e.push(n)):Array.isArray(n)&&n.forEach(function(a){la(a)&&(a.parent=f,e.push(a))}))}}catch(C){h=!0,u=C}finally{try{!a&&q.return&&q.return()}finally{if(h)throw u;}}}}return null}
|
|
21
|
+
function ma(a){for(var b="",e=0;e<a.length;e++)b+=a[e],0===e&&2===a.length?b+=" and ":e===a.length-2&&2<a.length?b+=", and ":e<a.length-1&&(b+=", ");return b}function la(a){return"object"===typeof a&&null!==a&&!Array.isArray(a)&&"string"===typeof a.type}function ea(a,b){return a.range[0]<=b.range[0]&&a.range[1]>=b.range[1]}
|
|
22
|
+
module.exports={rules:{"rules-of-hooks":{create:function(a){var b=[],e=[];return{onCodePathSegmentStart:function(a){return e.push(a)},onCodePathSegmentEnd:function(){return e.pop()},onCodePathStart:function(){return b.push(new Map)},onCodePathEnd:function(e,h){function f(a){var b=f.cache,c=b.get(a.id);if(null===c){if(!n.has(a.id)){n.add(a.id);b=!0;c=!1;var d=void 0;try{for(var m=a.prevSegments[Symbol.iterator](),r;!(b=(r=m.next()).done);b=!0)f(r.value)}catch(K){c=!0,d=K}finally{try{!b&&m.return&&
|
|
23
|
+
m.return()}finally{if(c)throw d;}}}return 0}if(void 0!==c)return c;b.set(a.id,null);if(e.thrownSegments.includes(a))c=0;else if(0===a.prevSegments.length)c=1;else{c=0;m=!0;r=!1;var H=void 0;try{d=a.prevSegments[Symbol.iterator]();for(var k;!(m=(k=d.next()).done);m=!0)c+=f(k.value)}catch(K){r=!0,H=K}finally{try{!m&&d.return&&d.return()}finally{if(r)throw H;}}}a.reachable&&0===c?b.delete(a.id):b.set(a.id,c);return c}function q(a){var b=q.cache,c=b.get(a.id);if(null===c){if(!n.has(a.id)){n.add(a.id);
|
|
24
|
+
b=!0;c=!1;var d=void 0;try{for(var m=a.nextSegments[Symbol.iterator](),r;!(b=(r=m.next()).done);b=!0)q(r.value)}catch(K){c=!0,d=K}finally{try{!b&&m.return&&m.return()}finally{if(c)throw d;}}}return 0}if(void 0!==c)return c;b.set(a.id,null);if(e.thrownSegments.includes(a))c=0;else if(0===a.nextSegments.length)c=1;else{c=0;m=!0;r=!1;var H=void 0;try{d=a.nextSegments[Symbol.iterator]();for(var f;!(m=(f=d.next()).done);m=!0)c+=q(f.value)}catch(K){r=!0,H=K}finally{try{!m&&d.return&&d.return()}finally{if(r)throw H;
|
|
25
|
+
}}}b.set(a.id,c);return c}function t(a){var c=t.cache,b=c.get(a.id);if(null===b)return Infinity;if(void 0!==b)return b;c.set(a.id,null);if(0===a.prevSegments.length)b=1;else{b=Infinity;var d=!0,m=!1,r=void 0;try{for(var H=a.prevSegments[Symbol.iterator](),e;!(d=(e=H.next()).done);d=!0){var f=t(e.value);f<b&&(b=f)}}catch(na){m=!0,r=na}finally{try{!d&&H.return&&H.return()}finally{if(m)throw r;}}b+=1}c.set(a.id,b);return b}var c=b.pop();if(0!==c.size){var n=new Set;f.cache=new Map;q.cache=new Map;t.cache=
|
|
26
|
+
new Map;var C=q(e.initialSegment),g=ca(h),v=ba(h),A=g?aa(g)||R(g):!1,B=Infinity,l=!0,p=!1,G=void 0;try{for(var w=e.finalSegments[Symbol.iterator](),J;!(l=(J=w.next()).done);l=!0){var W=J.value;if(W.reachable){var Q=t(W);Q<B&&(B=Q)}}}catch(k){p=!0,G=k}finally{try{!l&&w.return&&w.return()}finally{if(p)throw G;}}l=!0;p=!1;G=void 0;try{for(var z=c[Symbol.iterator](),O;!(l=(O=z.next()).done);l=!0){var E=O.value,D=E[0],L=E[1];if(D.reachable){var I=0===D.nextSegments.length?B<=t(D):B<t(D),T=f(D)*q(D),F=
|
|
27
|
+
n.has(D.id);c=!0;w=!1;J=void 0;try{for(var x=L[Symbol.iterator](),M;!(c=(M=x.next()).done);c=!0){var y=M.value;F&&a.report({node:y,message:'React Hook "'+a.getSource(y)+'" may be executed more than once. Possibly because it is called in a loop. React Hooks must be called in the exact same order in every component render.'});if(A){if(!F&&T!==C){var U='React Hook "'+a.getSource(y)+'" is called conditionally. React Hooks must be called in the exact same order in every component render.'+(I?" Did you accidentally call a React Hook after an early return?":
|
|
28
|
+
"");a.report({node:y,message:U})}}else if(!h.parent||"MethodDefinition"!==h.parent.type&&"ClassProperty"!==h.parent.type||h.parent.value!==h)if(g){var N='React Hook "'+a.getSource(y)+'" is called in '+('function "'+a.getSource(g)+'" ')+"which is neither a React function component or a custom React Hook function.";a.report({node:y,message:N})}else if("Program"!==h.type&&v){var P='React Hook "'+a.getSource(y)+'" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function.';
|
|
29
|
+
a.report({node:y,message:P})}}}catch(k){w=!0,J=k}finally{try{!c&&x.return&&x.return()}finally{if(w)throw J;}}}}}catch(k){p=!0,G=k}finally{try{!l&&z.return&&z.return()}finally{if(p)throw G;}}}},CallExpression:function(a){if(R(a.callee)){var f=b[b.length-1],u=e[e.length-1],q=f.get(u);q||(q=[],f.set(u,q));q.push(a.callee)}}}}},"exhaustive-deps":{meta:{fixable:"code",schema:[{type:"object",additionalProperties:!1,properties:{additionalHooks:{type:"string"}}}]},create:function(a){function b(a,b){return function(c){if(b.has(c))return b.get(c);
|
|
30
|
+
var e=a(c);b.set(c,e);return e}}function e(c){function e(a){var d=!0,r=!1,b=void 0;try{for(var f=a.references[Symbol.iterator](),h;!(d=(h=f.next()).done);d=!0){var g=h.value;if(g.resolved&&G.has(g.resolved.scope)){var l=Y(c,g.identifier),k=fa(l),p=X(k),q;if(q=B&&"Identifier"===k.type&&"MemberExpression"===k.parent.type&&!k.parent.computed&&"Identifier"===k.parent.property.type&&"current"===k.parent.property.name){for(var n=g.from,u=!1;n.block!==c;)"function"===n.type&&(u=null!=n.block.parent&&"ReturnStatement"===
|
|
31
|
+
n.block.parent.type),n=n.upper;q=u}q&&Q.set(p,{reference:g,dependencyNode:k});var t=g.resolved.defs[0];if(null==t||null==t.node||t.node.init!==c.parent)if(z.has(p))z.get(p).references.push(g);else{var v=g.resolved,y=J(v)||W(v);z.set(p,{isStatic:y,references:[g]})}}}}catch(Z){r=!0,b=Z}finally{try{!d&&f.return&&f.return()}finally{if(r)throw b;}}d=!0;r=!1;b=void 0;try{for(var w=a.childScopes[Symbol.iterator](),x;!(d=(x=w.next()).done);d=!0)e(x.value)}catch(Z){r=!0,b=Z}finally{try{!d&&w.return&&w.return()}finally{if(r)throw b;
|
|
32
|
+
}}}function C(a,b,r,c){return 0===a.size?null:(1<a.size?"":b+" ")+r+" "+(1<a.size?"dependencies":"dependency")+": "+ma(Array.from(a).sort().map(function(a){return"'"+a+"'"}))+(". Either "+c+" "+(1<a.size?"them":"it")+" or remove the dependency array.")}if(("FunctionExpression"===c.type||"ArrowFunctionExpression"===c.type)&&"CallExpression"===c.parent.type){var g=ka(c.parent.callee,f);if(c.parent.arguments[g]===c){var v=c.parent.callee,A=ja(v).name,B=A.endsWith("Effect"),l=c.parent.arguments[g+1];
|
|
33
|
+
if(l||B){B&&c.async&&a.report({node:c,message:"Effect callbacks are synchronous to prevent race conditions. Put the async function inside:\n\nuseEffect(() => {\n async function fetchData() {\n // You can await here\n const response = await MyAPI.getData(someId);\n // ...\n }\n fetchData();\n}, [someId]); // Or [] if effect doesn't need props or state\n\nLearn more about data fetching with Hooks: https://fb.me/react-hooks-data-fetching"});var p=a.getScope(),G=new Set,w=null;for(g=p.upper;g;){G.add(g);
|
|
34
|
+
if("function"===g.type)break;g=g.upper}if(g){w=g;var J=b(function(a){if(!Array.isArray(a.defs))return!1;var d=a.defs[0];if(null==d||"VariableDeclarator"!==d.node.type)return!1;var b=d.node.init;if(null==b)return!1;var c=d.node.parent;if(null==c&&(Y(w.block,d.node.id),c=d.node.parent,null==c))return!1;if("const"===c.kind&&"Literal"===b.type&&("string"===typeof b.value||"number"===typeof b.value||null===b.value))return!0;if("CallExpression"!==b.type)return!1;b=b.callee;"MemberExpression"!==b.type||
|
|
35
|
+
"React"!==b.object.name||null==b.property||b.computed||(b=b.property);if("Identifier"!==b.type)return!1;d=d.node.id;b=b.name;if("useRef"===b&&"Identifier"===d.type)return!0;if(("useState"===b||"useReducer"===b)&&"ArrayPattern"===d.type&&2===d.elements.length&&Array.isArray(a.identifiers)){if(d.elements[1]===a.identifiers[0]){if("useState"===b)for(a=a.references,b=0;b<a.length;b++)h.set(a[b].identifier,d.elements[0]);return!0}if(d.elements[0]===a.identifiers[0]&&"useState"===b)for(a=a.references,d=
|
|
36
|
+
0;d<a.length;d++)u.add(a[d].identifier)}return!1},q),W=b(function(a){if(!Array.isArray(a.defs))return!1;a=a.defs[0];if(null==a||null==a.node||null==a.node.id)return!1;var b=a.node,d=w.childScopes;a=null;var c;for(c=0;c<d.length;c++){var e=d[c],f=e.block;if("FunctionDeclaration"===b.type&&f===b||"VariableDeclarator"===b.type&&f.parent===b){a=e;break}}if(null==a)return!1;for(c=0;c<a.through.length;c++)if(b=a.through[c],null!=b.resolved&&G.has(b.resolved.scope)&&!J(b.resolved))return!1;return!0},t),
|
|
37
|
+
Q=new Map,z=new Map;e(p);Q.forEach(function(b,c){var d=b.dependencyNode;b=b.reference.resolved.references;for(var e=!1,f=0;f<b.length;f++){var m=b[f].identifier.parent;if(null!=m&&"MemberExpression"===m.type&&!m.computed&&"Identifier"===m.property.type&&"current"===m.property.name&&"AssignmentExpression"===m.parent.type&&m.parent.left===m){e=!0;break}}e||a.report({node:d.parent.property,message:"The ref value '"+c+".current' will likely have changed by the time this effect cleanup function runs. If this ref points to a node rendered by React, copy "+
|
|
38
|
+
("'"+c+".current' to a variable inside the effect, and ")+"use that variable in the cleanup function."})});var O=new Set,E=new Set;z.forEach(function(b,c){var d=b.references;b.isStatic&&E.add(c);d.forEach(function(b){b.writeExpr&&(b=b.writeExpr,O.has(c)||(O.add(c),a.report({node:b,message:"Assignments to the '"+c+"' variable from inside React Hook "+(a.getSource(v)+" will be lost after each ")+"render. To preserve the value over time, store it in a useRef Hook and keep the mutable value in the '.current' property. Otherwise, you can move this variable directly inside "+
|
|
39
|
+
(a.getSource(v)+".")})))})});if(!(0<O.size))if(l){var D=[],L=new Set;"ArrayExpression"!==l.type?a.report({node:l,message:"React Hook "+a.getSource(v)+" was passed a dependency list that is not an array literal. This means we can't statically verify whether you've passed the correct dependencies."}):l.elements.forEach(function(b){if(null!==b)if("SpreadElement"===b.type)a.report({node:b,message:"React Hook "+a.getSource(v)+" has a spread element in its dependency array. This means we can't statically verify whether you've passed the correct dependencies."});
|
|
40
|
+
else{var c=void 0;try{c=X(b)}catch(ia){if(/Unsupported node type/.test(ia.message)){"Literal"===b.type?z.has(b.value)?a.report({node:b,message:"The "+b.raw+" literal is not a valid dependency because it never changes. "+("Did you mean to include "+b.value+" in the array instead?")}):a.report({node:b,message:"The "+b.raw+" literal is not a valid dependency because it never changes. You can safely remove it."}):a.report({node:b,message:"React Hook "+a.getSource(v)+" has a complex expression in the dependency array. Extract it to a separate variable so it can be statically checked."});
|
|
41
|
+
return}throw ia;}for(var d=b;"MemberExpression"===d.type;)d=d.object;var e=!w.through.some(function(a){return a.identifier===d});D.push({key:c,node:b});e||L.add(c)}});var I=V({dependencies:z,declaredDependencies:D,optionalDependencies:E,externalDependencies:L,isEffect:B}),T=I.suggestedDependencies;g=I.unnecessaryDependencies;var F=I.missingDependencies;I=I.duplicateDependencies;if(0===I.size+F.size+g.size)da({declaredDependencies:D,declaredDependenciesNode:l,componentScope:w,scope:p}).forEach(function(b){var c=
|
|
42
|
+
b.fn,d=b.suggestUseCallback;b="The '"+c.name.name+"' function makes the dependencies of "+(A+" Hook (at line "+l.loc.start.line+") ")+"change on every render.";b=d?b+(" To fix this, "+("wrap the '"+c.name.name+"' definition into its own useCallback() Hook.")):b+(" Move it inside the "+A+" callback. "+("Alternatively, wrap the '"+c.name.name+"' definition into its own useCallback() Hook."));a.report({node:c.node,message:b,fix:function(a){if(d&&"Variable"===c.type)return[a.insertTextBefore(c.node.init,
|
|
43
|
+
"useCallback("),a.insertTextAfter(c.node.init,")")]}})});else{!B&&0<F.size&&(T=V({dependencies:z,declaredDependencies:[],optionalDependencies:E,externalDependencies:L,isEffect:B}).suggestedDependencies);(function(){if(0===D.length)return!0;var a=D.map(function(a){return a.key}),b=a.slice().sort();return a.join(",")===b.join(",")})()&&T.sort();var x="";if(0<g.size){var M=null;Array.from(g.keys()).forEach(function(a){null===M&&a.endsWith(".current")&&(M=a)});if(null!==M)x=" Mutable values like '"+M+
|
|
44
|
+
"' aren't valid dependencies because mutating them doesn't re-render the component.";else if(0<L.size){var y=Array.from(L)[0];p.set.has(y)||(x=" Outer scope values like '"+y+"' aren't valid dependencies because mutating them doesn't re-render the component.")}}if(!x&&F.has("props")){p=z.get("props");if(null==p)return;p=p.references;if(!Array.isArray(p))return;y=!0;for(var U=0;U<p.length;U++){var N=Y(w.block,p[U].identifier);if(!N){y=!1;break}N=N.parent;if(null==N){y=!1;break}if("MemberExpression"!==
|
|
45
|
+
N.type){y=!1;break}}y&&(x=" However, 'props' will change when *any* prop changes, so the preferred fix is to destructure the 'props' object outside of "+("the "+A+" call and refer to those specific props ")+("inside "+a.getSource(v)+"."))}if(!x&&0<F.size){var P=null;F.forEach(function(a){if(!P){var b=w.set.get(a),c=z.get(a);if(c.references[0].resolved===b&&(b=b.defs[0],null!=b&&null!=b.name&&"Parameter"===b.type)){b=!1;for(var d,e=0;e<c.references.length;e++)if(d=c.references[e].identifier,null!=
|
|
46
|
+
d&&null!=d.parent&&"CallExpression"===d.parent.type&&d.parent.callee===d){b=!0;break}b&&(P=a)}}});null!==P&&(x=" If '"+P+"' changes too often, find the parent component that defines it and wrap that definition in useCallback.")}if(!x&&0<F.size){var k=null;F.forEach(function(a){if(null===k)for(var b=z.get(a).references,c,d,e=0;e<b.length;e++){c=b[e].identifier;for(d=c.parent;null!=d&&d!==w.block;){if("CallExpression"===d.type){var f=h.get(d.callee);if(null!=f){f.name===a?k={missingDep:a,setter:d.callee.name,
|
|
47
|
+
form:"updater"}:u.has(c)?k={missingDep:a,setter:d.callee.name,form:"reducer"}:(c=b[e].resolved,null!=c&&(c=c.defs[0],null!=c&&"Parameter"===c.type&&(k={missingDep:a,setter:d.callee.name,form:"inlineReducer"})));break}}d=d.parent}if(null!==k)break}});if(null!==k)switch(k.form){case "reducer":x=" You can also replace multiple useState variables with useReducer "+("if '"+k.setter+"' needs the ")+("current value of '"+k.missingDep+"'.");break;case "inlineReducer":x=" If '"+k.setter+"' needs the "+("current value of '"+
|
|
48
|
+
k.missingDep+"', ")+"you can also switch to useReducer instead of useState and "+("read '"+k.missingDep+"' in the reducer.");break;case "updater":x=" You can also do a functional update '"+k.setter+"("+k.missingDep.substring(0,1)+" => ...)' if you only need '"+k.missingDep+"'"+(" in the '"+k.setter+"' call.");break;default:throw Error("Unknown case.");}}a.report({node:l,message:"React Hook "+a.getSource(v)+" has "+(C(F,"a","missing","include")||C(g,"an","unnecessary","exclude")||C(I,"a","duplicate",
|
|
49
|
+
"omit"))+x,fix:function(a){return a.replaceText(l,"["+T.join(", ")+"]")}})}}else{var S=null;z.forEach(function(a,b){S||a.references.forEach(function(a){if(!S&&h.has(a.identifier)){for(a=a.from;"function"!==a.type;)a=a.upper;a.block===c&&(S=b)}})});if(S){var ha=V({dependencies:z,declaredDependencies:[],optionalDependencies:E,externalDependencies:new Set,isEffect:!0}).suggestedDependencies;a.report({node:c.parent.callee,message:"React Hook "+A+" contains a call to '"+S+"'. Without a list of dependencies, this can lead to an infinite chain of updates. To fix this, pass ["+
|
|
50
|
+
ha.join(", ")+("] as a second argument to the "+A+" Hook."),fix:function(a){return a.insertTextAfter(c,", ["+ha.join(", ")+"]")}})}}}}else"useMemo"!==A&&"useCallback"!==A||a.report({node:c.parent.callee,message:"React Hook "+A+" does nothing when called with only one argument. Did you forget to pass an array of dependencies?"})}}}var f={additionalHooks:a.options&&a.options[0]&&a.options[0].additionalHooks?new RegExp(a.options[0].additionalHooks):void 0},h=new WeakMap,u=new WeakSet,q=new WeakMap,t=
|
|
51
|
+
new WeakMap;return{FunctionExpression:e,ArrowFunctionExpression:e}}}}};
|