Skip to content

Commit 4a8d929

Browse files
committed
[compiler] Show a ref name hint when assigning to non-ref in a callback (#34298)
In #34125 I added a hint where if you assign to the .current property of a frozen object, we suggest naming the variable as `ref` or `-Ref`. However, the tracking for mutations that assign to .current specifically wasn't propagated past function expression boundaries, which meant that the hint only showed up if you mutated the ref in the main body of the component/hook. That's less likely to happen since most folks know not to access refs in render. What's more likely is that you'll (correctly) assign a ref in an effect or callback, but the compiler will throw an error. By showing a hint in this case we can help people understand the naming pattern. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34298). * #34276 * __->__ #34298 DiffTrain build for [8d7b5e4](8d7b5e4)
1 parent 5f9db17 commit 4a8d929

35 files changed

+102
-95
lines changed

compiled/eslint-plugin-react-hooks/index.js

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19518,6 +19518,7 @@ function getFunctionName$2(instrValue, defaultValue) {
1951819518
}
1951919519
}
1952019520
function printAliasingEffect(effect) {
19521+
var _a;
1952119522
switch (effect.kind) {
1952219523
case 'Assign': {
1952319524
return `Assign ${printPlaceForAliasEffect(effect.into)} = ${printPlaceForAliasEffect(effect.from)}`;
@@ -19576,7 +19577,7 @@ function printAliasingEffect(effect) {
1957619577
case 'MutateConditionally':
1957719578
case 'MutateTransitive':
1957819579
case 'MutateTransitiveConditionally': {
19579-
return `${effect.kind} ${printPlaceForAliasEffect(effect.value)}`;
19580+
return `${effect.kind} ${printPlaceForAliasEffect(effect.value)}${effect.kind === 'Mutate' && ((_a = effect.reason) === null || _a === void 0 ? void 0 : _a.kind) === 'AssignCurrentProperty' ? ' (assign `.current`)' : ''}`;
1958019581
}
1958119582
case 'MutateFrozen': {
1958219583
return `MutateFrozen ${printPlaceForAliasEffect(effect.place)} reason=${JSON.stringify(effect.error.reason)}`;
@@ -42313,7 +42314,7 @@ class RewriteBlockIds extends ReactiveFunctionVisitor {
4231342314
}
4231442315

4231542316
function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
42316-
var _a, _b, _c, _d, _e, _f;
42317+
var _a, _b, _c, _d, _e, _f, _g;
4231742318
const functionEffects = [];
4231842319
const state = new AliasingState();
4231942320
const pendingPhis = new Map();
@@ -42380,6 +42381,7 @@ function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
4238042381
kind: effect.kind === 'MutateTransitive'
4238142382
? MutationKind.Definite
4238242383
: MutationKind.Conditional,
42384+
reason: null,
4238342385
place: effect.value,
4238442386
});
4238542387
}
@@ -42392,6 +42394,7 @@ function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
4239242394
kind: effect.kind === 'Mutate'
4239342395
? MutationKind.Definite
4239442396
: MutationKind.Conditional,
42397+
reason: effect.kind === 'Mutate' ? ((_a = effect.reason) !== null && _a !== void 0 ? _a : null) : null,
4239542398
place: effect.value,
4239642399
});
4239742400
}
@@ -42433,7 +42436,7 @@ function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
4243342436
}
4243442437
}
4243542438
for (const mutation of mutations) {
42436-
state.mutate(mutation.index, mutation.place.identifier, makeInstructionId(mutation.id + 1), mutation.transitive, mutation.kind, mutation.place.loc, errors);
42439+
state.mutate(mutation.index, mutation.place.identifier, makeInstructionId(mutation.id + 1), mutation.transitive, mutation.kind, mutation.place.loc, mutation.reason, errors);
4243742440
}
4243842441
for (const render of renders) {
4243942442
state.render(render.index, render.place.identifier, errors);
@@ -42458,6 +42461,7 @@ function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
4245842461
functionEffects.push({
4245942462
kind: 'Mutate',
4246042463
value: Object.assign(Object.assign({}, place), { loc: node.local.loc }),
42464+
reason: node.mutationReason,
4246142465
});
4246242466
}
4246342467
}
@@ -42485,15 +42489,15 @@ function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
4248542489
for (const phi of block.phis) {
4248642490
phi.place.effect = Effect.Store;
4248742491
const isPhiMutatedAfterCreation = phi.place.identifier.mutableRange.end >
42488-
((_b = (_a = block.instructions.at(0)) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : block.terminal.id);
42492+
((_c = (_b = block.instructions.at(0)) === null || _b === void 0 ? void 0 : _b.id) !== null && _c !== void 0 ? _c : block.terminal.id);
4248942493
for (const operand of phi.operands.values()) {
4249042494
operand.effect = isPhiMutatedAfterCreation
4249142495
? Effect.Capture
4249242496
: Effect.Read;
4249342497
}
4249442498
if (isPhiMutatedAfterCreation &&
4249542499
phi.place.identifier.mutableRange.start === 0) {
42496-
const firstInstructionIdOfBlock = (_d = (_c = block.instructions.at(0)) === null || _c === void 0 ? void 0 : _c.id) !== null && _d !== void 0 ? _d : block.terminal.id;
42500+
const firstInstructionIdOfBlock = (_e = (_d = block.instructions.at(0)) === null || _d === void 0 ? void 0 : _d.id) !== null && _e !== void 0 ? _e : block.terminal.id;
4249742501
phi.place.identifier.mutableRange.start = makeInstructionId(firstInstructionIdOfBlock - 1);
4249842502
}
4249942503
}
@@ -42571,15 +42575,15 @@ function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
4257142575
}
4257242576
}
4257342577
for (const lvalue of eachInstructionLValue(instr)) {
42574-
const effect = (_e = operandEffects.get(lvalue.identifier.id)) !== null && _e !== void 0 ? _e : Effect.ConditionallyMutate;
42578+
const effect = (_f = operandEffects.get(lvalue.identifier.id)) !== null && _f !== void 0 ? _f : Effect.ConditionallyMutate;
4257542579
lvalue.effect = effect;
4257642580
}
4257742581
for (const operand of eachInstructionValueOperand(instr.value)) {
4257842582
if (operand.identifier.mutableRange.end > instr.id &&
4257942583
operand.identifier.mutableRange.start === 0) {
4258042584
operand.identifier.mutableRange.start = instr.id;
4258142585
}
42582-
const effect = (_f = operandEffects.get(operand.identifier.id)) !== null && _f !== void 0 ? _f : Effect.Read;
42586+
const effect = (_g = operandEffects.get(operand.identifier.id)) !== null && _g !== void 0 ? _g : Effect.Read;
4258342587
operand.effect = effect;
4258442588
}
4258542589
if (instr.value.kind === 'StoreContext' &&
@@ -42617,7 +42621,7 @@ function inferMutationAliasingRanges(fn, { isFunctionExpression }) {
4261742621
}
4261842622
for (const into of tracked) {
4261942623
const mutationIndex = index++;
42620-
state.mutate(mutationIndex, into.identifier, null, true, MutationKind.Conditional, into.loc, ignoredErrors);
42624+
state.mutate(mutationIndex, into.identifier, null, true, MutationKind.Conditional, into.loc, null, ignoredErrors);
4262142625
for (const from of tracked) {
4262242626
if (from.identifier.id === into.identifier.id ||
4262342627
from.identifier.id === fn.returns.identifier.id) {
@@ -42685,6 +42689,7 @@ class AliasingState {
4268542689
transitive: null,
4268642690
local: null,
4268742691
lastMutated: 0,
42692+
mutationReason: null,
4268842693
value,
4268942694
});
4269042695
}
@@ -42769,7 +42774,8 @@ class AliasingState {
4276942774
}
4277042775
}
4277142776
}
42772-
mutate(index, start, end, transitive, startKind, loc, errors) {
42777+
mutate(index, start, end, transitive, startKind, loc, reason, errors) {
42778+
var _a;
4277342779
const seen = new Map();
4277442780
const queue = [{ place: start, transitive, direction: 'backwards', kind: startKind }];
4277542781
while (queue.length !== 0) {
@@ -42783,6 +42789,7 @@ class AliasingState {
4278342789
if (node == null) {
4278442790
continue;
4278542791
}
42792+
(_a = node.mutationReason) !== null && _a !== void 0 ? _a : (node.mutationReason = reason);
4278642793
node.lastMutated = Math.max(node.lastMutated, index);
4278742794
if (end != null) {
4278842795
node.id.mutableRange.end = makeInstructionId(Math.max(node.id.mutableRange.end, end));

compiled/facebook-www/REVISION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3434ff4f4b89ad9388c6109312ef95c14652ae21
1+
8d7b5e490320732f40d9c3aa4590b5b0ae5116f5
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3434ff4f4b89ad9388c6109312ef95c14652ae21
1+
8d7b5e490320732f40d9c3aa4590b5b0ae5116f5

compiled/facebook-www/React-dev.classic.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1409,7 +1409,7 @@ __DEV__ &&
14091409
exports.useTransition = function () {
14101410
return resolveDispatcher().useTransition();
14111411
};
1412-
exports.version = "19.2.0-www-classic-3434ff4f-20250827";
1412+
exports.version = "19.2.0-www-classic-8d7b5e49-20250827";
14131413
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
14141414
"function" ===
14151415
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/React-dev.modern.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1409,7 +1409,7 @@ __DEV__ &&
14091409
exports.useTransition = function () {
14101410
return resolveDispatcher().useTransition();
14111411
};
1412-
exports.version = "19.2.0-www-modern-3434ff4f-20250827";
1412+
exports.version = "19.2.0-www-modern-8d7b5e49-20250827";
14131413
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
14141414
"function" ===
14151415
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/React-prod.classic.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,4 +600,4 @@ exports.useSyncExternalStore = function (
600600
exports.useTransition = function () {
601601
return ReactSharedInternals.H.useTransition();
602602
};
603-
exports.version = "19.2.0-www-classic-3434ff4f-20250827";
603+
exports.version = "19.2.0-www-classic-8d7b5e49-20250827";

compiled/facebook-www/React-prod.modern.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,4 +600,4 @@ exports.useSyncExternalStore = function (
600600
exports.useTransition = function () {
601601
return ReactSharedInternals.H.useTransition();
602602
};
603-
exports.version = "19.2.0-www-modern-3434ff4f-20250827";
603+
exports.version = "19.2.0-www-modern-8d7b5e49-20250827";

compiled/facebook-www/React-profiling.classic.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@ exports.useSyncExternalStore = function (
604604
exports.useTransition = function () {
605605
return ReactSharedInternals.H.useTransition();
606606
};
607-
exports.version = "19.2.0-www-classic-3434ff4f-20250827";
607+
exports.version = "19.2.0-www-classic-8d7b5e49-20250827";
608608
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
609609
"function" ===
610610
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/React-profiling.modern.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@ exports.useSyncExternalStore = function (
604604
exports.useTransition = function () {
605605
return ReactSharedInternals.H.useTransition();
606606
};
607-
exports.version = "19.2.0-www-modern-3434ff4f-20250827";
607+
exports.version = "19.2.0-www-modern-8d7b5e49-20250827";
608608
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
609609
"function" ===
610610
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/ReactART-dev.classic.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19588,10 +19588,10 @@ __DEV__ &&
1958819588
(function () {
1958919589
var internals = {
1959019590
bundleType: 1,
19591-
version: "19.2.0-www-classic-3434ff4f-20250827",
19591+
version: "19.2.0-www-classic-8d7b5e49-20250827",
1959219592
rendererPackageName: "react-art",
1959319593
currentDispatcherRef: ReactSharedInternals,
19594-
reconcilerVersion: "19.2.0-www-classic-3434ff4f-20250827"
19594+
reconcilerVersion: "19.2.0-www-classic-8d7b5e49-20250827"
1959519595
};
1959619596
internals.overrideHookState = overrideHookState;
1959719597
internals.overrideHookStateDeletePath = overrideHookStateDeletePath;
@@ -19625,7 +19625,7 @@ __DEV__ &&
1962519625
exports.Shape = Shape;
1962619626
exports.Surface = Surface;
1962719627
exports.Text = Text;
19628-
exports.version = "19.2.0-www-classic-3434ff4f-20250827";
19628+
exports.version = "19.2.0-www-classic-8d7b5e49-20250827";
1962919629
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
1963019630
"function" ===
1963119631
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

0 commit comments

Comments
 (0)