eslint-plugin-react-hooks 6.1.0-canary-33a1095d-20250827 → 6.1.0-canary-89a803fc-20250828
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.
|
@@ -17972,6 +17972,7 @@ var ErrorCategory;
|
|
|
17972
17972
|
ErrorCategory["CapitalizedCalls"] = "CapitalizedCalls";
|
|
17973
17973
|
ErrorCategory["StaticComponents"] = "StaticComponents";
|
|
17974
17974
|
ErrorCategory["UseMemo"] = "UseMemo";
|
|
17975
|
+
ErrorCategory["Factories"] = "Factories";
|
|
17975
17976
|
ErrorCategory["PreserveManualMemo"] = "PreserveManualMemo";
|
|
17976
17977
|
ErrorCategory["Immutability"] = "Immutability";
|
|
17977
17978
|
ErrorCategory["Globals"] = "Globals";
|
|
@@ -18057,6 +18058,15 @@ function getRuleForCategoryImpl(category) {
|
|
|
18057
18058
|
recommended: true,
|
|
18058
18059
|
};
|
|
18059
18060
|
}
|
|
18061
|
+
case ErrorCategory.Factories: {
|
|
18062
|
+
return {
|
|
18063
|
+
category,
|
|
18064
|
+
name: 'component-hook-factories',
|
|
18065
|
+
description: 'Validates against higher order functions defining nested components or hooks. ' +
|
|
18066
|
+
'Components and hooks should be defined at the module level',
|
|
18067
|
+
recommended: true,
|
|
18068
|
+
};
|
|
18069
|
+
}
|
|
18060
18070
|
case ErrorCategory.FBT: {
|
|
18061
18071
|
return {
|
|
18062
18072
|
category,
|
|
@@ -19500,6 +19510,7 @@ function getFunctionName$2(instrValue, defaultValue) {
|
|
|
19500
19510
|
}
|
|
19501
19511
|
}
|
|
19502
19512
|
function printAliasingEffect(effect) {
|
|
19513
|
+
var _a;
|
|
19503
19514
|
switch (effect.kind) {
|
|
19504
19515
|
case 'Assign': {
|
|
19505
19516
|
return `Assign ${printPlaceForAliasEffect(effect.into)} = ${printPlaceForAliasEffect(effect.from)}`;
|
|
@@ -19558,7 +19569,7 @@ function printAliasingEffect(effect) {
|
|
|
19558
19569
|
case 'MutateConditionally':
|
|
19559
19570
|
case 'MutateTransitive':
|
|
19560
19571
|
case 'MutateTransitiveConditionally': {
|
|
19561
|
-
return `${effect.kind} ${printPlaceForAliasEffect(effect.value)}`;
|
|
19572
|
+
return `${effect.kind} ${printPlaceForAliasEffect(effect.value)}${effect.kind === 'Mutate' && ((_a = effect.reason) === null || _a === void 0 ? void 0 : _a.kind) === 'AssignCurrentProperty' ? ' (assign `.current`)' : ''}`;
|
|
19562
19573
|
}
|
|
19563
19574
|
case 'MutateFrozen': {
|
|
19564
19575
|
return `MutateFrozen ${printPlaceForAliasEffect(effect.place)} reason=${JSON.stringify(effect.error.reason)}`;
|
|
@@ -21070,7 +21081,7 @@ class HIRBuilder {
|
|
|
21070
21081
|
}
|
|
21071
21082
|
}
|
|
21072
21083
|
resolveBinding(node) {
|
|
21073
|
-
var _a, _b;
|
|
21084
|
+
var _a, _b, _c;
|
|
21074
21085
|
if (node.name === 'fbt') {
|
|
21075
21086
|
CompilerError.throwDiagnostic({
|
|
21076
21087
|
severity: ErrorSeverity.Todo,
|
|
@@ -21086,6 +21097,21 @@ class HIRBuilder {
|
|
|
21086
21097
|
],
|
|
21087
21098
|
});
|
|
21088
21099
|
}
|
|
21100
|
+
if (node.name === 'this') {
|
|
21101
|
+
CompilerError.throwDiagnostic({
|
|
21102
|
+
severity: ErrorSeverity.UnsupportedJS,
|
|
21103
|
+
category: ErrorCategory.UnsupportedSyntax,
|
|
21104
|
+
reason: '`this` is not supported syntax',
|
|
21105
|
+
description: 'React Compiler does not support compiling functions that use `this`',
|
|
21106
|
+
details: [
|
|
21107
|
+
{
|
|
21108
|
+
kind: 'error',
|
|
21109
|
+
message: '`this` was used here',
|
|
21110
|
+
loc: (_b = node.loc) !== null && _b !== void 0 ? _b : GeneratedSource,
|
|
21111
|
+
},
|
|
21112
|
+
],
|
|
21113
|
+
});
|
|
21114
|
+
}
|
|
21089
21115
|
const originalName = node.name;
|
|
21090
21116
|
let name = originalName;
|
|
21091
21117
|
let index = 0;
|
|
@@ -21103,7 +21129,7 @@ class HIRBuilder {
|
|
|
21103
21129
|
},
|
|
21104
21130
|
scope: null,
|
|
21105
21131
|
type: makeType(),
|
|
21106
|
-
loc: (
|
|
21132
|
+
loc: (_c = node.loc) !== null && _c !== void 0 ? _c : GeneratedSource,
|
|
21107
21133
|
};
|
|
21108
21134
|
__classPrivateFieldGet(this, _HIRBuilder_env, "f").programContext.addNewReference(name);
|
|
21109
21135
|
__classPrivateFieldGet(this, _HIRBuilder_bindings, "f").set(name, { node, identifier });
|
|
@@ -31612,6 +31638,7 @@ const EnvironmentConfigSchema = zod.z.object({
|
|
|
31612
31638
|
enableTreatRefLikeIdentifiersAsRefs: zod.z.boolean().default(true),
|
|
31613
31639
|
lowerContextAccess: ExternalFunctionSchema.nullable().default(null),
|
|
31614
31640
|
validateNoVoidUseMemo: zod.z.boolean().default(false),
|
|
31641
|
+
validateNoDynamicallyCreatedComponentsOrHooks: zod.z.boolean().default(false),
|
|
31615
31642
|
});
|
|
31616
31643
|
class Environment {
|
|
31617
31644
|
constructor(scope, fnType, compilerMode, config, contextIdentifiers, parentFunction, logger, filename, code, programContext) {
|
|
@@ -42237,7 +42264,7 @@ class RewriteBlockIds extends ReactiveFunctionVisitor {
|
|
|
42237
42264
|
}
|
|
42238
42265
|
|
|
42239
42266
|
function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
|
|
42240
|
-
var _a, _b, _c, _d, _e, _f;
|
|
42267
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
42241
42268
|
const functionEffects = [];
|
|
42242
42269
|
const state = new AliasingState();
|
|
42243
42270
|
const pendingPhis = new Map();
|
|
@@ -42304,6 +42331,7 @@ function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
|
|
|
42304
42331
|
kind: effect.kind === 'MutateTransitive'
|
|
42305
42332
|
? MutationKind.Definite
|
|
42306
42333
|
: MutationKind.Conditional,
|
|
42334
|
+
reason: null,
|
|
42307
42335
|
place: effect.value,
|
|
42308
42336
|
});
|
|
42309
42337
|
}
|
|
@@ -42316,6 +42344,7 @@ function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
|
|
|
42316
42344
|
kind: effect.kind === 'Mutate'
|
|
42317
42345
|
? MutationKind.Definite
|
|
42318
42346
|
: MutationKind.Conditional,
|
|
42347
|
+
reason: effect.kind === 'Mutate' ? ((_a = effect.reason) !== null && _a !== void 0 ? _a : null) : null,
|
|
42319
42348
|
place: effect.value,
|
|
42320
42349
|
});
|
|
42321
42350
|
}
|
|
@@ -42357,7 +42386,7 @@ function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
|
|
|
42357
42386
|
}
|
|
42358
42387
|
}
|
|
42359
42388
|
for (const mutation of mutations) {
|
|
42360
|
-
state.mutate(mutation.index, mutation.place.identifier, makeInstructionId(mutation.id + 1), mutation.transitive, mutation.kind, mutation.place.loc, errors);
|
|
42389
|
+
state.mutate(mutation.index, mutation.place.identifier, makeInstructionId(mutation.id + 1), mutation.transitive, mutation.kind, mutation.place.loc, mutation.reason, errors);
|
|
42361
42390
|
}
|
|
42362
42391
|
for (const render of renders) {
|
|
42363
42392
|
state.render(render.index, render.place.identifier, errors);
|
|
@@ -42382,6 +42411,7 @@ function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
|
|
|
42382
42411
|
functionEffects.push({
|
|
42383
42412
|
kind: 'Mutate',
|
|
42384
42413
|
value: Object.assign(Object.assign({}, place), { loc: node.local.loc }),
|
|
42414
|
+
reason: node.mutationReason,
|
|
42385
42415
|
});
|
|
42386
42416
|
}
|
|
42387
42417
|
}
|
|
@@ -42409,7 +42439,7 @@ function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
|
|
|
42409
42439
|
for (const phi of block.phis) {
|
|
42410
42440
|
phi.place.effect = Effect.Store;
|
|
42411
42441
|
const isPhiMutatedAfterCreation = phi.place.identifier.mutableRange.end >
|
|
42412
|
-
((
|
|
42442
|
+
((_c = (_b = block.instructions.at(0)) === null || _b === void 0 ? void 0 : _b.id) !== null && _c !== void 0 ? _c : block.terminal.id);
|
|
42413
42443
|
for (const operand of phi.operands.values()) {
|
|
42414
42444
|
operand.effect = isPhiMutatedAfterCreation
|
|
42415
42445
|
? Effect.Capture
|
|
@@ -42417,7 +42447,7 @@ function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
|
|
|
42417
42447
|
}
|
|
42418
42448
|
if (isPhiMutatedAfterCreation &&
|
|
42419
42449
|
phi.place.identifier.mutableRange.start === 0) {
|
|
42420
|
-
const firstInstructionIdOfBlock = (
|
|
42450
|
+
const firstInstructionIdOfBlock = (_e = (_d = block.instructions.at(0)) === null || _d === void 0 ? void 0 : _d.id) !== null && _e !== void 0 ? _e : block.terminal.id;
|
|
42421
42451
|
phi.place.identifier.mutableRange.start = makeInstructionId(firstInstructionIdOfBlock - 1);
|
|
42422
42452
|
}
|
|
42423
42453
|
}
|
|
@@ -42495,7 +42525,7 @@ function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
|
|
|
42495
42525
|
}
|
|
42496
42526
|
}
|
|
42497
42527
|
for (const lvalue of eachInstructionLValue(instr)) {
|
|
42498
|
-
const effect = (
|
|
42528
|
+
const effect = (_f = operandEffects.get(lvalue.identifier.id)) !== null && _f !== void 0 ? _f : Effect.ConditionallyMutate;
|
|
42499
42529
|
lvalue.effect = effect;
|
|
42500
42530
|
}
|
|
42501
42531
|
for (const operand of eachInstructionValueOperand(instr.value)) {
|
|
@@ -42503,7 +42533,7 @@ function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
|
|
|
42503
42533
|
operand.identifier.mutableRange.start === 0) {
|
|
42504
42534
|
operand.identifier.mutableRange.start = instr.id;
|
|
42505
42535
|
}
|
|
42506
|
-
const effect = (
|
|
42536
|
+
const effect = (_g = operandEffects.get(operand.identifier.id)) !== null && _g !== void 0 ? _g : Effect.Read;
|
|
42507
42537
|
operand.effect = effect;
|
|
42508
42538
|
}
|
|
42509
42539
|
if (instr.value.kind === 'StoreContext' &&
|
|
@@ -42541,7 +42571,7 @@ function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
|
|
|
42541
42571
|
}
|
|
42542
42572
|
for (const into of tracked) {
|
|
42543
42573
|
const mutationIndex = index++;
|
|
42544
|
-
state.mutate(mutationIndex, into.identifier, null, true, MutationKind.Conditional, into.loc, ignoredErrors);
|
|
42574
|
+
state.mutate(mutationIndex, into.identifier, null, true, MutationKind.Conditional, into.loc, null, ignoredErrors);
|
|
42545
42575
|
for (const from of tracked) {
|
|
42546
42576
|
if (from.identifier.id === into.identifier.id ||
|
|
42547
42577
|
from.identifier.id === fn.returns.identifier.id) {
|
|
@@ -42609,6 +42639,7 @@ class AliasingState {
|
|
|
42609
42639
|
transitive: null,
|
|
42610
42640
|
local: null,
|
|
42611
42641
|
lastMutated: 0,
|
|
42642
|
+
mutationReason: null,
|
|
42612
42643
|
value,
|
|
42613
42644
|
});
|
|
42614
42645
|
}
|
|
@@ -42693,7 +42724,8 @@ class AliasingState {
|
|
|
42693
42724
|
}
|
|
42694
42725
|
}
|
|
42695
42726
|
}
|
|
42696
|
-
mutate(index, start, end, transitive, startKind, loc, errors) {
|
|
42727
|
+
mutate(index, start, end, transitive, startKind, loc, reason, errors) {
|
|
42728
|
+
var _a;
|
|
42697
42729
|
const seen = new Map();
|
|
42698
42730
|
const queue = [{ place: start, transitive, direction: 'backwards', kind: startKind }];
|
|
42699
42731
|
while (queue.length !== 0) {
|
|
@@ -42707,6 +42739,7 @@ class AliasingState {
|
|
|
42707
42739
|
if (node == null) {
|
|
42708
42740
|
continue;
|
|
42709
42741
|
}
|
|
42742
|
+
(_a = node.mutationReason) !== null && _a !== void 0 ? _a : (node.mutationReason = reason);
|
|
42710
42743
|
node.lastMutated = Math.max(node.lastMutated, index);
|
|
42711
42744
|
if (end != null) {
|
|
42712
42745
|
node.id.mutableRange.end = makeInstructionId(Math.max(node.id.mutableRange.end, end));
|
|
@@ -50942,7 +50975,14 @@ function findFunctionsToCompile(program, pass, programContext) {
|
|
|
50942
50975
|
var _a;
|
|
50943
50976
|
const queue = [];
|
|
50944
50977
|
const traverseFunction = (fn, pass) => {
|
|
50978
|
+
if (pass.opts.compilationMode === 'all' &&
|
|
50979
|
+
fn.scope.getProgramParent() !== fn.scope.parent) {
|
|
50980
|
+
return;
|
|
50981
|
+
}
|
|
50945
50982
|
const fnType = getReactFunctionType(fn, pass);
|
|
50983
|
+
if (pass.opts.environment.validateNoDynamicallyCreatedComponentsOrHooks) {
|
|
50984
|
+
validateNoDynamicallyCreatedComponentsOrHooks(fn, pass, programContext);
|
|
50985
|
+
}
|
|
50946
50986
|
if (fnType === null || programContext.alreadyCompiled.has(fn.node)) {
|
|
50947
50987
|
return;
|
|
50948
50988
|
}
|
|
@@ -51127,6 +51167,52 @@ function shouldSkipCompilation(program, pass) {
|
|
|
51127
51167
|
}
|
|
51128
51168
|
return false;
|
|
51129
51169
|
}
|
|
51170
|
+
function validateNoDynamicallyCreatedComponentsOrHooks(fn, pass, programContext) {
|
|
51171
|
+
const parentNameExpr = getFunctionName$1(fn);
|
|
51172
|
+
const parentName = parentNameExpr !== null && parentNameExpr.isIdentifier()
|
|
51173
|
+
? parentNameExpr.node.name
|
|
51174
|
+
: '<anonymous>';
|
|
51175
|
+
const validateNestedFunction = (nestedFn) => {
|
|
51176
|
+
var _a, _b, _c, _d;
|
|
51177
|
+
if (nestedFn.node === fn.node ||
|
|
51178
|
+
programContext.alreadyCompiled.has(nestedFn.node)) {
|
|
51179
|
+
return;
|
|
51180
|
+
}
|
|
51181
|
+
if (nestedFn.scope.getProgramParent() !== nestedFn.scope.parent) {
|
|
51182
|
+
const nestedFnType = getReactFunctionType(nestedFn, pass);
|
|
51183
|
+
const nestedFnNameExpr = getFunctionName$1(nestedFn);
|
|
51184
|
+
const nestedName = nestedFnNameExpr !== null && nestedFnNameExpr.isIdentifier()
|
|
51185
|
+
? nestedFnNameExpr.node.name
|
|
51186
|
+
: '<anonymous>';
|
|
51187
|
+
if (nestedFnType === 'Component' || nestedFnType === 'Hook') {
|
|
51188
|
+
CompilerError.throwDiagnostic({
|
|
51189
|
+
category: ErrorCategory.Factories,
|
|
51190
|
+
severity: ErrorSeverity.InvalidReact,
|
|
51191
|
+
reason: `Components and hooks cannot be created dynamically`,
|
|
51192
|
+
description: `The function \`${nestedName}\` appears to be a React ${nestedFnType.toLowerCase()}, but it's defined inside \`${parentName}\`. Components and Hooks should always be declared at module scope`,
|
|
51193
|
+
details: [
|
|
51194
|
+
{
|
|
51195
|
+
kind: 'error',
|
|
51196
|
+
message: 'this function dynamically created a component/hook',
|
|
51197
|
+
loc: (_b = (_a = parentNameExpr === null || parentNameExpr === void 0 ? void 0 : parentNameExpr.node.loc) !== null && _a !== void 0 ? _a : fn.node.loc) !== null && _b !== void 0 ? _b : null,
|
|
51198
|
+
},
|
|
51199
|
+
{
|
|
51200
|
+
kind: 'error',
|
|
51201
|
+
message: 'the component is created here',
|
|
51202
|
+
loc: (_d = (_c = nestedFnNameExpr === null || nestedFnNameExpr === void 0 ? void 0 : nestedFnNameExpr.node.loc) !== null && _c !== void 0 ? _c : nestedFn.node.loc) !== null && _d !== void 0 ? _d : null,
|
|
51203
|
+
},
|
|
51204
|
+
],
|
|
51205
|
+
});
|
|
51206
|
+
}
|
|
51207
|
+
}
|
|
51208
|
+
nestedFn.skip();
|
|
51209
|
+
};
|
|
51210
|
+
fn.traverse({
|
|
51211
|
+
FunctionDeclaration: validateNestedFunction,
|
|
51212
|
+
FunctionExpression: validateNestedFunction,
|
|
51213
|
+
ArrowFunctionExpression: validateNestedFunction,
|
|
51214
|
+
});
|
|
51215
|
+
}
|
|
51130
51216
|
function getReactFunctionType(fn, pass) {
|
|
51131
51217
|
var _a, _b;
|
|
51132
51218
|
const hookPattern = pass.opts.environment.hookPattern;
|
|
@@ -51156,9 +51242,6 @@ function getReactFunctionType(fn, pass) {
|
|
|
51156
51242
|
return componentSyntaxType;
|
|
51157
51243
|
}
|
|
51158
51244
|
case 'all': {
|
|
51159
|
-
if (fn.scope.getProgramParent() !== fn.scope.parent) {
|
|
51160
|
-
return null;
|
|
51161
|
-
}
|
|
51162
51245
|
return (_b = getComponentOrHookLike(fn, hookPattern)) !== null && _b !== void 0 ? _b : 'Other';
|
|
51163
51246
|
}
|
|
51164
51247
|
default: {
|
|
@@ -17963,6 +17963,7 @@ var ErrorCategory;
|
|
|
17963
17963
|
ErrorCategory["CapitalizedCalls"] = "CapitalizedCalls";
|
|
17964
17964
|
ErrorCategory["StaticComponents"] = "StaticComponents";
|
|
17965
17965
|
ErrorCategory["UseMemo"] = "UseMemo";
|
|
17966
|
+
ErrorCategory["Factories"] = "Factories";
|
|
17966
17967
|
ErrorCategory["PreserveManualMemo"] = "PreserveManualMemo";
|
|
17967
17968
|
ErrorCategory["Immutability"] = "Immutability";
|
|
17968
17969
|
ErrorCategory["Globals"] = "Globals";
|
|
@@ -18048,6 +18049,15 @@ function getRuleForCategoryImpl(category) {
|
|
|
18048
18049
|
recommended: true,
|
|
18049
18050
|
};
|
|
18050
18051
|
}
|
|
18052
|
+
case ErrorCategory.Factories: {
|
|
18053
|
+
return {
|
|
18054
|
+
category,
|
|
18055
|
+
name: 'component-hook-factories',
|
|
18056
|
+
description: 'Validates against higher order functions defining nested components or hooks. ' +
|
|
18057
|
+
'Components and hooks should be defined at the module level',
|
|
18058
|
+
recommended: true,
|
|
18059
|
+
};
|
|
18060
|
+
}
|
|
18051
18061
|
case ErrorCategory.FBT: {
|
|
18052
18062
|
return {
|
|
18053
18063
|
category,
|
|
@@ -19491,6 +19501,7 @@ function getFunctionName$2(instrValue, defaultValue) {
|
|
|
19491
19501
|
}
|
|
19492
19502
|
}
|
|
19493
19503
|
function printAliasingEffect(effect) {
|
|
19504
|
+
var _a;
|
|
19494
19505
|
switch (effect.kind) {
|
|
19495
19506
|
case 'Assign': {
|
|
19496
19507
|
return `Assign ${printPlaceForAliasEffect(effect.into)} = ${printPlaceForAliasEffect(effect.from)}`;
|
|
@@ -19549,7 +19560,7 @@ function printAliasingEffect(effect) {
|
|
|
19549
19560
|
case 'MutateConditionally':
|
|
19550
19561
|
case 'MutateTransitive':
|
|
19551
19562
|
case 'MutateTransitiveConditionally': {
|
|
19552
|
-
return `${effect.kind} ${printPlaceForAliasEffect(effect.value)}`;
|
|
19563
|
+
return `${effect.kind} ${printPlaceForAliasEffect(effect.value)}${effect.kind === 'Mutate' && ((_a = effect.reason) === null || _a === void 0 ? void 0 : _a.kind) === 'AssignCurrentProperty' ? ' (assign `.current`)' : ''}`;
|
|
19553
19564
|
}
|
|
19554
19565
|
case 'MutateFrozen': {
|
|
19555
19566
|
return `MutateFrozen ${printPlaceForAliasEffect(effect.place)} reason=${JSON.stringify(effect.error.reason)}`;
|
|
@@ -21061,7 +21072,7 @@ class HIRBuilder {
|
|
|
21061
21072
|
}
|
|
21062
21073
|
}
|
|
21063
21074
|
resolveBinding(node) {
|
|
21064
|
-
var _a, _b;
|
|
21075
|
+
var _a, _b, _c;
|
|
21065
21076
|
if (node.name === 'fbt') {
|
|
21066
21077
|
CompilerError.throwDiagnostic({
|
|
21067
21078
|
severity: ErrorSeverity.Todo,
|
|
@@ -21077,6 +21088,21 @@ class HIRBuilder {
|
|
|
21077
21088
|
],
|
|
21078
21089
|
});
|
|
21079
21090
|
}
|
|
21091
|
+
if (node.name === 'this') {
|
|
21092
|
+
CompilerError.throwDiagnostic({
|
|
21093
|
+
severity: ErrorSeverity.UnsupportedJS,
|
|
21094
|
+
category: ErrorCategory.UnsupportedSyntax,
|
|
21095
|
+
reason: '`this` is not supported syntax',
|
|
21096
|
+
description: 'React Compiler does not support compiling functions that use `this`',
|
|
21097
|
+
details: [
|
|
21098
|
+
{
|
|
21099
|
+
kind: 'error',
|
|
21100
|
+
message: '`this` was used here',
|
|
21101
|
+
loc: (_b = node.loc) !== null && _b !== void 0 ? _b : GeneratedSource,
|
|
21102
|
+
},
|
|
21103
|
+
],
|
|
21104
|
+
});
|
|
21105
|
+
}
|
|
21080
21106
|
const originalName = node.name;
|
|
21081
21107
|
let name = originalName;
|
|
21082
21108
|
let index = 0;
|
|
@@ -21094,7 +21120,7 @@ class HIRBuilder {
|
|
|
21094
21120
|
},
|
|
21095
21121
|
scope: null,
|
|
21096
21122
|
type: makeType(),
|
|
21097
|
-
loc: (
|
|
21123
|
+
loc: (_c = node.loc) !== null && _c !== void 0 ? _c : GeneratedSource,
|
|
21098
21124
|
};
|
|
21099
21125
|
__classPrivateFieldGet(this, _HIRBuilder_env, "f").programContext.addNewReference(name);
|
|
21100
21126
|
__classPrivateFieldGet(this, _HIRBuilder_bindings, "f").set(name, { node, identifier });
|
|
@@ -31439,6 +31465,7 @@ const EnvironmentConfigSchema = zod.z.object({
|
|
|
31439
31465
|
enableTreatRefLikeIdentifiersAsRefs: zod.z.boolean().default(true),
|
|
31440
31466
|
lowerContextAccess: ExternalFunctionSchema.nullable().default(null),
|
|
31441
31467
|
validateNoVoidUseMemo: zod.z.boolean().default(false),
|
|
31468
|
+
validateNoDynamicallyCreatedComponentsOrHooks: zod.z.boolean().default(false),
|
|
31442
31469
|
});
|
|
31443
31470
|
class Environment {
|
|
31444
31471
|
constructor(scope, fnType, compilerMode, config, contextIdentifiers, parentFunction, logger, filename, code, programContext) {
|
|
@@ -42064,7 +42091,7 @@ class RewriteBlockIds extends ReactiveFunctionVisitor {
|
|
|
42064
42091
|
}
|
|
42065
42092
|
|
|
42066
42093
|
function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
|
|
42067
|
-
var _a, _b, _c, _d, _e, _f;
|
|
42094
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
42068
42095
|
const functionEffects = [];
|
|
42069
42096
|
const state = new AliasingState();
|
|
42070
42097
|
const pendingPhis = new Map();
|
|
@@ -42131,6 +42158,7 @@ function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
|
|
|
42131
42158
|
kind: effect.kind === 'MutateTransitive'
|
|
42132
42159
|
? MutationKind.Definite
|
|
42133
42160
|
: MutationKind.Conditional,
|
|
42161
|
+
reason: null,
|
|
42134
42162
|
place: effect.value,
|
|
42135
42163
|
});
|
|
42136
42164
|
}
|
|
@@ -42143,6 +42171,7 @@ function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
|
|
|
42143
42171
|
kind: effect.kind === 'Mutate'
|
|
42144
42172
|
? MutationKind.Definite
|
|
42145
42173
|
: MutationKind.Conditional,
|
|
42174
|
+
reason: effect.kind === 'Mutate' ? ((_a = effect.reason) !== null && _a !== void 0 ? _a : null) : null,
|
|
42146
42175
|
place: effect.value,
|
|
42147
42176
|
});
|
|
42148
42177
|
}
|
|
@@ -42184,7 +42213,7 @@ function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
|
|
|
42184
42213
|
}
|
|
42185
42214
|
}
|
|
42186
42215
|
for (const mutation of mutations) {
|
|
42187
|
-
state.mutate(mutation.index, mutation.place.identifier, makeInstructionId(mutation.id + 1), mutation.transitive, mutation.kind, mutation.place.loc, errors);
|
|
42216
|
+
state.mutate(mutation.index, mutation.place.identifier, makeInstructionId(mutation.id + 1), mutation.transitive, mutation.kind, mutation.place.loc, mutation.reason, errors);
|
|
42188
42217
|
}
|
|
42189
42218
|
for (const render of renders) {
|
|
42190
42219
|
state.render(render.index, render.place.identifier, errors);
|
|
@@ -42209,6 +42238,7 @@ function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
|
|
|
42209
42238
|
functionEffects.push({
|
|
42210
42239
|
kind: 'Mutate',
|
|
42211
42240
|
value: Object.assign(Object.assign({}, place), { loc: node.local.loc }),
|
|
42241
|
+
reason: node.mutationReason,
|
|
42212
42242
|
});
|
|
42213
42243
|
}
|
|
42214
42244
|
}
|
|
@@ -42236,7 +42266,7 @@ function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
|
|
|
42236
42266
|
for (const phi of block.phis) {
|
|
42237
42267
|
phi.place.effect = Effect.Store;
|
|
42238
42268
|
const isPhiMutatedAfterCreation = phi.place.identifier.mutableRange.end >
|
|
42239
|
-
((
|
|
42269
|
+
((_c = (_b = block.instructions.at(0)) === null || _b === void 0 ? void 0 : _b.id) !== null && _c !== void 0 ? _c : block.terminal.id);
|
|
42240
42270
|
for (const operand of phi.operands.values()) {
|
|
42241
42271
|
operand.effect = isPhiMutatedAfterCreation
|
|
42242
42272
|
? Effect.Capture
|
|
@@ -42244,7 +42274,7 @@ function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
|
|
|
42244
42274
|
}
|
|
42245
42275
|
if (isPhiMutatedAfterCreation &&
|
|
42246
42276
|
phi.place.identifier.mutableRange.start === 0) {
|
|
42247
|
-
const firstInstructionIdOfBlock = (
|
|
42277
|
+
const firstInstructionIdOfBlock = (_e = (_d = block.instructions.at(0)) === null || _d === void 0 ? void 0 : _d.id) !== null && _e !== void 0 ? _e : block.terminal.id;
|
|
42248
42278
|
phi.place.identifier.mutableRange.start = makeInstructionId(firstInstructionIdOfBlock - 1);
|
|
42249
42279
|
}
|
|
42250
42280
|
}
|
|
@@ -42322,7 +42352,7 @@ function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
|
|
|
42322
42352
|
}
|
|
42323
42353
|
}
|
|
42324
42354
|
for (const lvalue of eachInstructionLValue(instr)) {
|
|
42325
|
-
const effect = (
|
|
42355
|
+
const effect = (_f = operandEffects.get(lvalue.identifier.id)) !== null && _f !== void 0 ? _f : Effect.ConditionallyMutate;
|
|
42326
42356
|
lvalue.effect = effect;
|
|
42327
42357
|
}
|
|
42328
42358
|
for (const operand of eachInstructionValueOperand(instr.value)) {
|
|
@@ -42330,7 +42360,7 @@ function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
|
|
|
42330
42360
|
operand.identifier.mutableRange.start === 0) {
|
|
42331
42361
|
operand.identifier.mutableRange.start = instr.id;
|
|
42332
42362
|
}
|
|
42333
|
-
const effect = (
|
|
42363
|
+
const effect = (_g = operandEffects.get(operand.identifier.id)) !== null && _g !== void 0 ? _g : Effect.Read;
|
|
42334
42364
|
operand.effect = effect;
|
|
42335
42365
|
}
|
|
42336
42366
|
if (instr.value.kind === 'StoreContext' &&
|
|
@@ -42368,7 +42398,7 @@ function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
|
|
|
42368
42398
|
}
|
|
42369
42399
|
for (const into of tracked) {
|
|
42370
42400
|
const mutationIndex = index++;
|
|
42371
|
-
state.mutate(mutationIndex, into.identifier, null, true, MutationKind.Conditional, into.loc, ignoredErrors);
|
|
42401
|
+
state.mutate(mutationIndex, into.identifier, null, true, MutationKind.Conditional, into.loc, null, ignoredErrors);
|
|
42372
42402
|
for (const from of tracked) {
|
|
42373
42403
|
if (from.identifier.id === into.identifier.id ||
|
|
42374
42404
|
from.identifier.id === fn.returns.identifier.id) {
|
|
@@ -42436,6 +42466,7 @@ class AliasingState {
|
|
|
42436
42466
|
transitive: null,
|
|
42437
42467
|
local: null,
|
|
42438
42468
|
lastMutated: 0,
|
|
42469
|
+
mutationReason: null,
|
|
42439
42470
|
value,
|
|
42440
42471
|
});
|
|
42441
42472
|
}
|
|
@@ -42520,7 +42551,8 @@ class AliasingState {
|
|
|
42520
42551
|
}
|
|
42521
42552
|
}
|
|
42522
42553
|
}
|
|
42523
|
-
mutate(index, start, end, transitive, startKind, loc, errors) {
|
|
42554
|
+
mutate(index, start, end, transitive, startKind, loc, reason, errors) {
|
|
42555
|
+
var _a;
|
|
42524
42556
|
const seen = new Map();
|
|
42525
42557
|
const queue = [{ place: start, transitive, direction: 'backwards', kind: startKind }];
|
|
42526
42558
|
while (queue.length !== 0) {
|
|
@@ -42534,6 +42566,7 @@ class AliasingState {
|
|
|
42534
42566
|
if (node == null) {
|
|
42535
42567
|
continue;
|
|
42536
42568
|
}
|
|
42569
|
+
(_a = node.mutationReason) !== null && _a !== void 0 ? _a : (node.mutationReason = reason);
|
|
42537
42570
|
node.lastMutated = Math.max(node.lastMutated, index);
|
|
42538
42571
|
if (end != null) {
|
|
42539
42572
|
node.id.mutableRange.end = makeInstructionId(Math.max(node.id.mutableRange.end, end));
|
|
@@ -50769,7 +50802,14 @@ function findFunctionsToCompile(program, pass, programContext) {
|
|
|
50769
50802
|
var _a;
|
|
50770
50803
|
const queue = [];
|
|
50771
50804
|
const traverseFunction = (fn, pass) => {
|
|
50805
|
+
if (pass.opts.compilationMode === 'all' &&
|
|
50806
|
+
fn.scope.getProgramParent() !== fn.scope.parent) {
|
|
50807
|
+
return;
|
|
50808
|
+
}
|
|
50772
50809
|
const fnType = getReactFunctionType(fn, pass);
|
|
50810
|
+
if (pass.opts.environment.validateNoDynamicallyCreatedComponentsOrHooks) {
|
|
50811
|
+
validateNoDynamicallyCreatedComponentsOrHooks(fn, pass, programContext);
|
|
50812
|
+
}
|
|
50773
50813
|
if (fnType === null || programContext.alreadyCompiled.has(fn.node)) {
|
|
50774
50814
|
return;
|
|
50775
50815
|
}
|
|
@@ -50954,6 +50994,52 @@ function shouldSkipCompilation(program, pass) {
|
|
|
50954
50994
|
}
|
|
50955
50995
|
return false;
|
|
50956
50996
|
}
|
|
50997
|
+
function validateNoDynamicallyCreatedComponentsOrHooks(fn, pass, programContext) {
|
|
50998
|
+
const parentNameExpr = getFunctionName$1(fn);
|
|
50999
|
+
const parentName = parentNameExpr !== null && parentNameExpr.isIdentifier()
|
|
51000
|
+
? parentNameExpr.node.name
|
|
51001
|
+
: '<anonymous>';
|
|
51002
|
+
const validateNestedFunction = (nestedFn) => {
|
|
51003
|
+
var _a, _b, _c, _d;
|
|
51004
|
+
if (nestedFn.node === fn.node ||
|
|
51005
|
+
programContext.alreadyCompiled.has(nestedFn.node)) {
|
|
51006
|
+
return;
|
|
51007
|
+
}
|
|
51008
|
+
if (nestedFn.scope.getProgramParent() !== nestedFn.scope.parent) {
|
|
51009
|
+
const nestedFnType = getReactFunctionType(nestedFn, pass);
|
|
51010
|
+
const nestedFnNameExpr = getFunctionName$1(nestedFn);
|
|
51011
|
+
const nestedName = nestedFnNameExpr !== null && nestedFnNameExpr.isIdentifier()
|
|
51012
|
+
? nestedFnNameExpr.node.name
|
|
51013
|
+
: '<anonymous>';
|
|
51014
|
+
if (nestedFnType === 'Component' || nestedFnType === 'Hook') {
|
|
51015
|
+
CompilerError.throwDiagnostic({
|
|
51016
|
+
category: ErrorCategory.Factories,
|
|
51017
|
+
severity: ErrorSeverity.InvalidReact,
|
|
51018
|
+
reason: `Components and hooks cannot be created dynamically`,
|
|
51019
|
+
description: `The function \`${nestedName}\` appears to be a React ${nestedFnType.toLowerCase()}, but it's defined inside \`${parentName}\`. Components and Hooks should always be declared at module scope`,
|
|
51020
|
+
details: [
|
|
51021
|
+
{
|
|
51022
|
+
kind: 'error',
|
|
51023
|
+
message: 'this function dynamically created a component/hook',
|
|
51024
|
+
loc: (_b = (_a = parentNameExpr === null || parentNameExpr === void 0 ? void 0 : parentNameExpr.node.loc) !== null && _a !== void 0 ? _a : fn.node.loc) !== null && _b !== void 0 ? _b : null,
|
|
51025
|
+
},
|
|
51026
|
+
{
|
|
51027
|
+
kind: 'error',
|
|
51028
|
+
message: 'the component is created here',
|
|
51029
|
+
loc: (_d = (_c = nestedFnNameExpr === null || nestedFnNameExpr === void 0 ? void 0 : nestedFnNameExpr.node.loc) !== null && _c !== void 0 ? _c : nestedFn.node.loc) !== null && _d !== void 0 ? _d : null,
|
|
51030
|
+
},
|
|
51031
|
+
],
|
|
51032
|
+
});
|
|
51033
|
+
}
|
|
51034
|
+
}
|
|
51035
|
+
nestedFn.skip();
|
|
51036
|
+
};
|
|
51037
|
+
fn.traverse({
|
|
51038
|
+
FunctionDeclaration: validateNestedFunction,
|
|
51039
|
+
FunctionExpression: validateNestedFunction,
|
|
51040
|
+
ArrowFunctionExpression: validateNestedFunction,
|
|
51041
|
+
});
|
|
51042
|
+
}
|
|
50957
51043
|
function getReactFunctionType(fn, pass) {
|
|
50958
51044
|
var _a, _b;
|
|
50959
51045
|
const hookPattern = pass.opts.environment.hookPattern;
|
|
@@ -50983,9 +51069,6 @@ function getReactFunctionType(fn, pass) {
|
|
|
50983
51069
|
return componentSyntaxType;
|
|
50984
51070
|
}
|
|
50985
51071
|
case 'all': {
|
|
50986
|
-
if (fn.scope.getProgramParent() !== fn.scope.parent) {
|
|
50987
|
-
return null;
|
|
50988
|
-
}
|
|
50989
51072
|
return (_b = getComponentOrHookLike(fn, hookPattern)) !== null && _b !== void 0 ? _b : 'Other';
|
|
50990
51073
|
}
|
|
50991
51074
|
default: {
|
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-canary-
|
|
4
|
+
"version": "6.1.0-canary-89a803fc-20250828",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "https://github.com/facebook/react.git",
|