eslint-plugin-react-hooks 6.1.0 → 6.2.0-canary-85c427d8-20251003

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.
@@ -1,11 +1,10 @@
1
1
  import * as estree from 'estree';
2
- import { Rule } from 'eslint';
2
+ import { Rule, Linter } from 'eslint';
3
3
 
4
4
  declare const plugin: {
5
5
  meta: {
6
6
  name: string;
7
7
  };
8
- configs: {};
9
8
  rules: {
10
9
  'exhaustive-deps': {
11
10
  meta: {
@@ -73,6 +72,19 @@ declare const plugin: {
73
72
  };
74
73
  };
75
74
  };
75
+ configs: {
76
+ "recommended-legacy": {
77
+ plugins: Array<string>;
78
+ rules: Linter.RulesRecord;
79
+ };
80
+ "recommended-latest-legacy": {
81
+ plugins: Array<string>;
82
+ rules: Linter.RulesRecord;
83
+ };
84
+ "flat/recommended": Array<Linter.Config>;
85
+ "recommended-latest": Array<Linter.Config>;
86
+ recommended: Array<Linter.Config>;
87
+ };
76
88
  };
77
89
 
78
90
  export { plugin as default };
@@ -19,7 +19,6 @@ var BabelParser = require('@babel/parser');
19
19
  var zod = require('zod');
20
20
  var zodValidationError = require('zod-validation-error');
21
21
  var crypto = require('crypto');
22
- var PluginProposalPrivateMethods = require('@babel/plugin-proposal-private-methods');
23
22
  var HermesParser = require('hermes-parser');
24
23
  var util = require('util');
25
24
 
@@ -32075,7 +32074,7 @@ const EnvironmentConfigSchema = zod.z.object({
32075
32074
  moduleTypeProvider: zod.z.nullable(zod.z.function().args(zod.z.string())).default(null),
32076
32075
  customMacros: zod.z.nullable(zod.z.array(MacroSchema)).default(null),
32077
32076
  enableResetCacheOnSourceFileChanges: zod.z.nullable(zod.z.boolean()).default(null),
32078
- enablePreserveExistingMemoizationGuarantees: zod.z.boolean().default(false),
32077
+ enablePreserveExistingMemoizationGuarantees: zod.z.boolean().default(true),
32079
32078
  validatePreserveExistingMemoizationGuarantees: zod.z.boolean().default(true),
32080
32079
  enablePreserveExistingManualUseMemo: zod.z.boolean().default(false),
32081
32080
  enableForest: zod.z.boolean().default(false),
@@ -45315,6 +45314,29 @@ function collectNonNullsInBlocks(fn, context) {
45315
45314
  }
45316
45315
  }
45317
45316
  }
45317
+ else if (fn.env.config.enablePreserveExistingMemoizationGuarantees &&
45318
+ instr.value.kind === 'StartMemoize' &&
45319
+ instr.value.deps != null) {
45320
+ for (const dep of instr.value.deps) {
45321
+ if (dep.root.kind === 'NamedLocal') {
45322
+ if (!isImmutableAtInstr(dep.root.value.identifier, instr.id, context)) {
45323
+ continue;
45324
+ }
45325
+ for (let i = 0; i < dep.path.length; i++) {
45326
+ const pathEntry = dep.path[i];
45327
+ if (pathEntry.optional) {
45328
+ break;
45329
+ }
45330
+ const depNode = context.registry.getOrCreateProperty({
45331
+ identifier: dep.root.value.identifier,
45332
+ path: dep.path.slice(0, i),
45333
+ reactive: dep.root.value.reactive,
45334
+ });
45335
+ assumedNonNullObjects.add(depNode);
45336
+ }
45337
+ }
45338
+ }
45339
+ }
45318
45340
  }
45319
45341
  nodes.set(block.id, {
45320
45342
  block,
@@ -54127,20 +54149,6 @@ function getFlowSuppressions(sourceCode) {
54127
54149
  }
54128
54150
  return results;
54129
54151
  }
54130
- function filterUnusedOptOutDirectives(directives) {
54131
- const results = [];
54132
- for (const directive of directives) {
54133
- if (OPT_OUT_DIRECTIVES.has(directive.value.value) &&
54134
- directive.loc != null) {
54135
- results.push({
54136
- loc: directive.loc,
54137
- directive: directive.value.value,
54138
- range: [directive.start, directive.end],
54139
- });
54140
- }
54141
- }
54142
- return results;
54143
- }
54144
54152
  function runReactCompilerImpl({ sourceCode, filename, userOpts, }) {
54145
54153
  var _a, _b;
54146
54154
  const options = parsePluginOptions(Object.assign(Object.assign(Object.assign({}, COMPILER_OPTIONS), userOpts), { environment: Object.assign(Object.assign({}, COMPILER_OPTIONS.environment), userOpts.environment) }));
@@ -54149,7 +54157,6 @@ function runReactCompilerImpl({ sourceCode, filename, userOpts, }) {
54149
54157
  filename,
54150
54158
  userOpts,
54151
54159
  flowSuppressions: [],
54152
- unusedOptOutDirectives: [],
54153
54160
  events: [],
54154
54161
  };
54155
54162
  const userLogger = options.logger;
@@ -54196,29 +54203,11 @@ function runReactCompilerImpl({ sourceCode, filename, userOpts, }) {
54196
54203
  filename,
54197
54204
  highlightCode: false,
54198
54205
  retainLines: true,
54199
- plugins: [
54200
- [PluginProposalPrivateMethods.default, { loose: true }],
54201
- [BabelPluginReactCompiler, options],
54202
- ],
54206
+ plugins: [[BabelPluginReactCompiler, options]],
54203
54207
  sourceType: 'module',
54204
54208
  configFile: false,
54205
54209
  babelrc: false,
54206
54210
  });
54207
- if (results.events.filter(e => e.kind === 'CompileError').length === 0) {
54208
- core$1.traverse(babelAST, {
54209
- FunctionDeclaration(path) {
54210
- results.unusedOptOutDirectives.push(...filterUnusedOptOutDirectives(path.node.body.directives));
54211
- },
54212
- ArrowFunctionExpression(path) {
54213
- if (path.node.body.type === 'BlockStatement') {
54214
- results.unusedOptOutDirectives.push(...filterUnusedOptOutDirectives(path.node.body.directives));
54215
- }
54216
- },
54217
- FunctionExpression(path) {
54218
- results.unusedOptOutDirectives.push(...filterUnusedOptOutDirectives(path.node.body.directives));
54219
- },
54220
- });
54221
- }
54222
54211
  }
54223
54212
  catch (err) {
54224
54213
  }
@@ -54388,53 +54377,31 @@ function makeRule(rule) {
54388
54377
  create,
54389
54378
  };
54390
54379
  }
54391
- const NoUnusedDirectivesRule = {
54392
- meta: {
54393
- type: 'suggestion',
54394
- docs: {
54395
- recommended: true,
54396
- },
54397
- fixable: 'code',
54398
- hasSuggestions: true,
54399
- schema: [{ type: 'object', additionalProperties: true }],
54400
- },
54401
- create(context) {
54402
- const results = getReactCompilerResult(context);
54403
- for (const directive of results.unusedOptOutDirectives) {
54404
- context.report({
54405
- message: `Unused '${directive.directive}' directive`,
54406
- loc: directive.loc,
54407
- suggest: [
54408
- {
54409
- desc: 'Remove the directive',
54410
- fix(fixer) {
54411
- return fixer.removeRange(directive.range);
54412
- },
54413
- },
54414
- ],
54415
- });
54416
- }
54417
- return {};
54418
- },
54419
- };
54420
54380
  const allRules = LintRules.reduce((acc, rule) => {
54421
54381
  acc[rule.name] = { rule: makeRule(rule), severity: rule.severity };
54422
54382
  return acc;
54423
- }, {
54424
- 'no-unused-directives': {
54425
- rule: NoUnusedDirectivesRule,
54426
- severity: ErrorSeverity.Error,
54427
- },
54428
- });
54429
- LintRules.filter(rule => rule.recommended).reduce((acc, rule) => {
54383
+ }, {});
54384
+ const recommendedRules = LintRules.filter(rule => rule.recommended).reduce((acc, rule) => {
54430
54385
  acc[rule.name] = { rule: makeRule(rule), severity: rule.severity };
54431
54386
  return acc;
54432
- }, {
54433
- 'no-unused-directives': {
54434
- rule: NoUnusedDirectivesRule,
54435
- severity: ErrorSeverity.Error,
54436
- },
54437
- });
54387
+ }, {});
54388
+ function mapErrorSeverityToESlint(severity) {
54389
+ switch (severity) {
54390
+ case ErrorSeverity.Error: {
54391
+ return 'error';
54392
+ }
54393
+ case ErrorSeverity.Warning: {
54394
+ return 'warn';
54395
+ }
54396
+ case ErrorSeverity.Hint:
54397
+ case ErrorSeverity.Off: {
54398
+ return 'off';
54399
+ }
54400
+ default: {
54401
+ assertExhaustive(severity, `Unhandled severity: ${severity}`);
54402
+ }
54403
+ }
54404
+ }
54438
54405
 
54439
54406
  var assert_1;
54440
54407
  var hasRequiredAssert;
@@ -57722,28 +57689,39 @@ function last(array) {
57722
57689
  }
57723
57690
 
57724
57691
  const rules = Object.assign({ 'exhaustive-deps': rule$1, 'rules-of-hooks': rule }, Object.fromEntries(Object.entries(allRules).map(([name, config]) => [name, config.rule])));
57725
- const ruleConfigs = {
57692
+ const basicRuleConfigs = {
57726
57693
  'react-hooks/rules-of-hooks': 'error',
57727
57694
  'react-hooks/exhaustive-deps': 'warn',
57728
57695
  };
57696
+ const compilerRuleConfigs = Object.fromEntries(Object.entries(recommendedRules).map(([name, ruleConfig]) => {
57697
+ return [
57698
+ `react-hooks/${name}`,
57699
+ mapErrorSeverityToESlint(ruleConfig.severity),
57700
+ ];
57701
+ }));
57702
+ const allRuleConfigs = Object.assign(Object.assign({}, basicRuleConfigs), compilerRuleConfigs);
57729
57703
  const plugin = {
57730
57704
  meta: {
57731
57705
  name: 'eslint-plugin-react-hooks',
57732
57706
  },
57733
- configs: {},
57734
57707
  rules,
57708
+ configs: {},
57735
57709
  };
57736
57710
  Object.assign(plugin.configs, {
57737
57711
  'recommended-legacy': {
57738
57712
  plugins: ['react-hooks'],
57739
- rules: ruleConfigs,
57713
+ rules: basicRuleConfigs,
57714
+ },
57715
+ 'recommended-latest-legacy': {
57716
+ plugins: ['react-hooks'],
57717
+ rules: allRuleConfigs,
57740
57718
  },
57741
57719
  'flat/recommended': [
57742
57720
  {
57743
57721
  plugins: {
57744
57722
  'react-hooks': plugin,
57745
57723
  },
57746
- rules: ruleConfigs,
57724
+ rules: basicRuleConfigs,
57747
57725
  },
57748
57726
  ],
57749
57727
  'recommended-latest': [
@@ -57751,13 +57729,17 @@ Object.assign(plugin.configs, {
57751
57729
  plugins: {
57752
57730
  'react-hooks': plugin,
57753
57731
  },
57754
- rules: ruleConfigs,
57732
+ rules: allRuleConfigs,
57733
+ },
57734
+ ],
57735
+ recommended: [
57736
+ {
57737
+ plugins: {
57738
+ 'react-hooks': plugin,
57739
+ },
57740
+ rules: basicRuleConfigs,
57755
57741
  },
57756
57742
  ],
57757
- recommended: {
57758
- plugins: ['react-hooks'],
57759
- rules: ruleConfigs,
57760
- },
57761
57743
  });
57762
57744
 
57763
57745
  module.exports = plugin;
@@ -15,7 +15,6 @@ var BabelParser = require('@babel/parser');
15
15
  var zod = require('zod');
16
16
  var zodValidationError = require('zod-validation-error');
17
17
  var crypto = require('crypto');
18
- var PluginProposalPrivateMethods = require('@babel/plugin-proposal-private-methods');
19
18
  var HermesParser = require('hermes-parser');
20
19
  var util = require('util');
21
20
 
@@ -31902,7 +31901,7 @@ const EnvironmentConfigSchema = zod.z.object({
31902
31901
  moduleTypeProvider: zod.z.nullable(zod.z.function().args(zod.z.string())).default(null),
31903
31902
  customMacros: zod.z.nullable(zod.z.array(MacroSchema)).default(null),
31904
31903
  enableResetCacheOnSourceFileChanges: zod.z.nullable(zod.z.boolean()).default(null),
31905
- enablePreserveExistingMemoizationGuarantees: zod.z.boolean().default(false),
31904
+ enablePreserveExistingMemoizationGuarantees: zod.z.boolean().default(true),
31906
31905
  validatePreserveExistingMemoizationGuarantees: zod.z.boolean().default(true),
31907
31906
  enablePreserveExistingManualUseMemo: zod.z.boolean().default(false),
31908
31907
  enableForest: zod.z.boolean().default(false),
@@ -45142,6 +45141,29 @@ function collectNonNullsInBlocks(fn, context) {
45142
45141
  }
45143
45142
  }
45144
45143
  }
45144
+ else if (fn.env.config.enablePreserveExistingMemoizationGuarantees &&
45145
+ instr.value.kind === 'StartMemoize' &&
45146
+ instr.value.deps != null) {
45147
+ for (const dep of instr.value.deps) {
45148
+ if (dep.root.kind === 'NamedLocal') {
45149
+ if (!isImmutableAtInstr(dep.root.value.identifier, instr.id, context)) {
45150
+ continue;
45151
+ }
45152
+ for (let i = 0; i < dep.path.length; i++) {
45153
+ const pathEntry = dep.path[i];
45154
+ if (pathEntry.optional) {
45155
+ break;
45156
+ }
45157
+ const depNode = context.registry.getOrCreateProperty({
45158
+ identifier: dep.root.value.identifier,
45159
+ path: dep.path.slice(0, i),
45160
+ reactive: dep.root.value.reactive,
45161
+ });
45162
+ assumedNonNullObjects.add(depNode);
45163
+ }
45164
+ }
45165
+ }
45166
+ }
45145
45167
  }
45146
45168
  nodes.set(block.id, {
45147
45169
  block,
@@ -53954,20 +53976,6 @@ function getFlowSuppressions(sourceCode) {
53954
53976
  }
53955
53977
  return results;
53956
53978
  }
53957
- function filterUnusedOptOutDirectives(directives) {
53958
- const results = [];
53959
- for (const directive of directives) {
53960
- if (OPT_OUT_DIRECTIVES.has(directive.value.value) &&
53961
- directive.loc != null) {
53962
- results.push({
53963
- loc: directive.loc,
53964
- directive: directive.value.value,
53965
- range: [directive.start, directive.end],
53966
- });
53967
- }
53968
- }
53969
- return results;
53970
- }
53971
53979
  function runReactCompilerImpl({ sourceCode, filename, userOpts, }) {
53972
53980
  var _a, _b;
53973
53981
  const options = parsePluginOptions(Object.assign(Object.assign(Object.assign({}, COMPILER_OPTIONS), userOpts), { environment: Object.assign(Object.assign({}, COMPILER_OPTIONS.environment), userOpts.environment) }));
@@ -53976,7 +53984,6 @@ function runReactCompilerImpl({ sourceCode, filename, userOpts, }) {
53976
53984
  filename,
53977
53985
  userOpts,
53978
53986
  flowSuppressions: [],
53979
- unusedOptOutDirectives: [],
53980
53987
  events: [],
53981
53988
  };
53982
53989
  const userLogger = options.logger;
@@ -54023,29 +54030,11 @@ function runReactCompilerImpl({ sourceCode, filename, userOpts, }) {
54023
54030
  filename,
54024
54031
  highlightCode: false,
54025
54032
  retainLines: true,
54026
- plugins: [
54027
- [PluginProposalPrivateMethods.default, { loose: true }],
54028
- [BabelPluginReactCompiler, options],
54029
- ],
54033
+ plugins: [[BabelPluginReactCompiler, options]],
54030
54034
  sourceType: 'module',
54031
54035
  configFile: false,
54032
54036
  babelrc: false,
54033
54037
  });
54034
- if (results.events.filter(e => e.kind === 'CompileError').length === 0) {
54035
- core$1.traverse(babelAST, {
54036
- FunctionDeclaration(path) {
54037
- results.unusedOptOutDirectives.push(...filterUnusedOptOutDirectives(path.node.body.directives));
54038
- },
54039
- ArrowFunctionExpression(path) {
54040
- if (path.node.body.type === 'BlockStatement') {
54041
- results.unusedOptOutDirectives.push(...filterUnusedOptOutDirectives(path.node.body.directives));
54042
- }
54043
- },
54044
- FunctionExpression(path) {
54045
- results.unusedOptOutDirectives.push(...filterUnusedOptOutDirectives(path.node.body.directives));
54046
- },
54047
- });
54048
- }
54049
54038
  }
54050
54039
  catch (err) {
54051
54040
  }
@@ -54215,53 +54204,31 @@ function makeRule(rule) {
54215
54204
  create,
54216
54205
  };
54217
54206
  }
54218
- const NoUnusedDirectivesRule = {
54219
- meta: {
54220
- type: 'suggestion',
54221
- docs: {
54222
- recommended: true,
54223
- },
54224
- fixable: 'code',
54225
- hasSuggestions: true,
54226
- schema: [{ type: 'object', additionalProperties: true }],
54227
- },
54228
- create(context) {
54229
- const results = getReactCompilerResult(context);
54230
- for (const directive of results.unusedOptOutDirectives) {
54231
- context.report({
54232
- message: `Unused '${directive.directive}' directive`,
54233
- loc: directive.loc,
54234
- suggest: [
54235
- {
54236
- desc: 'Remove the directive',
54237
- fix(fixer) {
54238
- return fixer.removeRange(directive.range);
54239
- },
54240
- },
54241
- ],
54242
- });
54243
- }
54244
- return {};
54245
- },
54246
- };
54247
54207
  const allRules = LintRules.reduce((acc, rule) => {
54248
54208
  acc[rule.name] = { rule: makeRule(rule), severity: rule.severity };
54249
54209
  return acc;
54250
- }, {
54251
- 'no-unused-directives': {
54252
- rule: NoUnusedDirectivesRule,
54253
- severity: ErrorSeverity.Error,
54254
- },
54255
- });
54256
- LintRules.filter(rule => rule.recommended).reduce((acc, rule) => {
54210
+ }, {});
54211
+ const recommendedRules = LintRules.filter(rule => rule.recommended).reduce((acc, rule) => {
54257
54212
  acc[rule.name] = { rule: makeRule(rule), severity: rule.severity };
54258
54213
  return acc;
54259
- }, {
54260
- 'no-unused-directives': {
54261
- rule: NoUnusedDirectivesRule,
54262
- severity: ErrorSeverity.Error,
54263
- },
54264
- });
54214
+ }, {});
54215
+ function mapErrorSeverityToESlint(severity) {
54216
+ switch (severity) {
54217
+ case ErrorSeverity.Error: {
54218
+ return 'error';
54219
+ }
54220
+ case ErrorSeverity.Warning: {
54221
+ return 'warn';
54222
+ }
54223
+ case ErrorSeverity.Hint:
54224
+ case ErrorSeverity.Off: {
54225
+ return 'off';
54226
+ }
54227
+ default: {
54228
+ assertExhaustive(severity, `Unhandled severity: ${severity}`);
54229
+ }
54230
+ }
54231
+ }
54265
54232
 
54266
54233
  var assert_1;
54267
54234
  var hasRequiredAssert;
@@ -57549,28 +57516,39 @@ function last(array) {
57549
57516
  }
57550
57517
 
57551
57518
  const rules = Object.assign({ 'exhaustive-deps': rule$1, 'rules-of-hooks': rule }, Object.fromEntries(Object.entries(allRules).map(([name, config]) => [name, config.rule])));
57552
- const ruleConfigs = {
57519
+ const basicRuleConfigs = {
57553
57520
  'react-hooks/rules-of-hooks': 'error',
57554
57521
  'react-hooks/exhaustive-deps': 'warn',
57555
57522
  };
57523
+ const compilerRuleConfigs = Object.fromEntries(Object.entries(recommendedRules).map(([name, ruleConfig]) => {
57524
+ return [
57525
+ `react-hooks/${name}`,
57526
+ mapErrorSeverityToESlint(ruleConfig.severity),
57527
+ ];
57528
+ }));
57529
+ const allRuleConfigs = Object.assign(Object.assign({}, basicRuleConfigs), compilerRuleConfigs);
57556
57530
  const plugin = {
57557
57531
  meta: {
57558
57532
  name: 'eslint-plugin-react-hooks',
57559
57533
  },
57560
- configs: {},
57561
57534
  rules,
57535
+ configs: {},
57562
57536
  };
57563
57537
  Object.assign(plugin.configs, {
57564
57538
  'recommended-legacy': {
57565
57539
  plugins: ['react-hooks'],
57566
- rules: ruleConfigs,
57540
+ rules: basicRuleConfigs,
57541
+ },
57542
+ 'recommended-latest-legacy': {
57543
+ plugins: ['react-hooks'],
57544
+ rules: allRuleConfigs,
57567
57545
  },
57568
57546
  'flat/recommended': [
57569
57547
  {
57570
57548
  plugins: {
57571
57549
  'react-hooks': plugin,
57572
57550
  },
57573
- rules: ruleConfigs,
57551
+ rules: basicRuleConfigs,
57574
57552
  },
57575
57553
  ],
57576
57554
  'recommended-latest': [
@@ -57578,13 +57556,17 @@ Object.assign(plugin.configs, {
57578
57556
  plugins: {
57579
57557
  'react-hooks': plugin,
57580
57558
  },
57581
- rules: ruleConfigs,
57559
+ rules: allRuleConfigs,
57560
+ },
57561
+ ],
57562
+ recommended: [
57563
+ {
57564
+ plugins: {
57565
+ 'react-hooks': plugin,
57566
+ },
57567
+ rules: basicRuleConfigs,
57582
57568
  },
57583
57569
  ],
57584
- recommended: {
57585
- plugins: ['react-hooks'],
57586
- rules: ruleConfigs,
57587
- },
57588
57570
  });
57589
57571
 
57590
57572
  module.exports = plugin;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "eslint-plugin-react-hooks",
3
3
  "description": "ESLint rules for React Hooks",
4
- "version": "6.1.0",
4
+ "version": "6.2.0-canary-85c427d8-20251003",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/facebook/react.git",
@@ -41,7 +41,6 @@
41
41
  "dependencies": {
42
42
  "@babel/core": "^7.24.4",
43
43
  "@babel/parser": "^7.24.4",
44
- "@babel/plugin-proposal-private-methods": "^7.18.6",
45
44
  "hermes-parser": "^0.25.1",
46
45
  "zod": "^3.22.4",
47
46
  "zod-validation-error": "^3.0.3"