Skip to content

Commit 4e22ee1

Browse files
committed
[DevTools] Reorder moved filtered Fibers with backing DevToolsInstance (facebook#34104)
Instead, we just continue to collect the unfiltered children. --------- Co-authored-by: Sebastian Sebbie Silbermann <[email protected]> DiffTrain build for [99fd4f2](facebook@99fd4f2)
1 parent 889e084 commit 4e22ee1

35 files changed

+251
-132
lines changed

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

Lines changed: 165 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -30871,6 +30871,7 @@ const EnvironmentConfigSchema = zod.z.object({
3087130871
validateRefAccessDuringRender: zod.z.boolean().default(true),
3087230872
validateNoSetStateInRender: zod.z.boolean().default(true),
3087330873
validateNoSetStateInEffects: zod.z.boolean().default(false),
30874+
validateNoDerivedComputationsInEffects: zod.z.boolean().default(false),
3087430875
validateNoJSXInTryStatements: zod.z.boolean().default(false),
3087530876
validateStaticComponents: zod.z.boolean().default(false),
3087630877
validateMemoizedEffectDependencies: zod.z.boolean().default(false),
@@ -49629,46 +49630,6 @@ function outlineFunctions(fn, fbtOperands) {
4962949630
}
4963049631
}
4963149632

49632-
function propagatePhiTypes(fn) {
49633-
const propagated = new Set();
49634-
for (const [, block] of fn.body.blocks) {
49635-
for (const phi of block.phis) {
49636-
if (phi.place.identifier.type.kind !== 'Type' ||
49637-
phi.place.identifier.name !== null) {
49638-
continue;
49639-
}
49640-
let type = null;
49641-
for (const [, operand] of phi.operands) {
49642-
if (type === null) {
49643-
type = operand.identifier.type;
49644-
}
49645-
else if (!typeEquals(type, operand.identifier.type)) {
49646-
type = null;
49647-
break;
49648-
}
49649-
}
49650-
if (type !== null) {
49651-
phi.place.identifier.type = type;
49652-
propagated.add(phi.place.identifier.id);
49653-
}
49654-
}
49655-
for (const instr of block.instructions) {
49656-
const { value } = instr;
49657-
switch (value.kind) {
49658-
case 'StoreLocal': {
49659-
const lvalue = value.lvalue.place;
49660-
if (propagated.has(value.value.identifier.id) &&
49661-
lvalue.identifier.type.kind === 'Type' &&
49662-
lvalue.identifier.name === null) {
49663-
lvalue.identifier.type = value.value.identifier.type;
49664-
propagated.add(lvalue.identifier.id);
49665-
}
49666-
}
49667-
}
49668-
}
49669-
}
49670-
}
49671-
4967249633
function lowerContextAccess(fn, loweredContextCalleeConfig) {
4967349634
const contextAccess = new Map();
4967449635
const contextKeys = new Map();
@@ -51050,6 +51011,167 @@ function validateNoFreezingKnownMutableFunctions(fn) {
5105051011
return errors.asResult();
5105151012
}
5105251013

51014+
function validateNoDerivedComputationsInEffects(fn) {
51015+
const candidateDependencies = new Map();
51016+
const functions = new Map();
51017+
const locals = new Map();
51018+
const errors = new CompilerError();
51019+
for (const block of fn.body.blocks.values()) {
51020+
for (const instr of block.instructions) {
51021+
const { lvalue, value } = instr;
51022+
if (value.kind === 'LoadLocal') {
51023+
locals.set(lvalue.identifier.id, value.place.identifier.id);
51024+
}
51025+
else if (value.kind === 'ArrayExpression') {
51026+
candidateDependencies.set(lvalue.identifier.id, value);
51027+
}
51028+
else if (value.kind === 'FunctionExpression') {
51029+
functions.set(lvalue.identifier.id, value);
51030+
}
51031+
else if (value.kind === 'CallExpression' ||
51032+
value.kind === 'MethodCall') {
51033+
const callee = value.kind === 'CallExpression' ? value.callee : value.property;
51034+
if (isUseEffectHookType(callee.identifier) &&
51035+
value.args.length === 2 &&
51036+
value.args[0].kind === 'Identifier' &&
51037+
value.args[1].kind === 'Identifier') {
51038+
const effectFunction = functions.get(value.args[0].identifier.id);
51039+
const deps = candidateDependencies.get(value.args[1].identifier.id);
51040+
if (effectFunction != null &&
51041+
deps != null &&
51042+
deps.elements.length !== 0 &&
51043+
deps.elements.every(element => element.kind === 'Identifier')) {
51044+
const dependencies = deps.elements.map(dep => {
51045+
var _a;
51046+
CompilerError.invariant(dep.kind === 'Identifier', {
51047+
reason: `Dependency is checked as a place above`,
51048+
loc: value.loc,
51049+
});
51050+
return (_a = locals.get(dep.identifier.id)) !== null && _a !== void 0 ? _a : dep.identifier.id;
51051+
});
51052+
validateEffect(effectFunction.loweredFunc.func, dependencies, errors);
51053+
}
51054+
}
51055+
}
51056+
}
51057+
}
51058+
if (errors.hasErrors()) {
51059+
throw errors;
51060+
}
51061+
}
51062+
function validateEffect(effectFunction, effectDeps, errors) {
51063+
for (const operand of effectFunction.context) {
51064+
if (isSetStateType(operand.identifier)) {
51065+
continue;
51066+
}
51067+
else if (effectDeps.find(dep => dep === operand.identifier.id) != null) {
51068+
continue;
51069+
}
51070+
else {
51071+
return;
51072+
}
51073+
}
51074+
for (const dep of effectDeps) {
51075+
if (effectFunction.context.find(operand => operand.identifier.id === dep) ==
51076+
null) {
51077+
return;
51078+
}
51079+
}
51080+
const seenBlocks = new Set();
51081+
const values = new Map();
51082+
for (const dep of effectDeps) {
51083+
values.set(dep, [dep]);
51084+
}
51085+
const setStateLocations = [];
51086+
for (const block of effectFunction.body.blocks.values()) {
51087+
for (const pred of block.preds) {
51088+
if (!seenBlocks.has(pred)) {
51089+
return;
51090+
}
51091+
}
51092+
for (const phi of block.phis) {
51093+
const aggregateDeps = new Set();
51094+
for (const operand of phi.operands.values()) {
51095+
const deps = values.get(operand.identifier.id);
51096+
if (deps != null) {
51097+
for (const dep of deps) {
51098+
aggregateDeps.add(dep);
51099+
}
51100+
}
51101+
}
51102+
if (aggregateDeps.size !== 0) {
51103+
values.set(phi.place.identifier.id, Array.from(aggregateDeps));
51104+
}
51105+
}
51106+
for (const instr of block.instructions) {
51107+
switch (instr.value.kind) {
51108+
case 'Primitive':
51109+
case 'JSXText':
51110+
case 'LoadGlobal': {
51111+
break;
51112+
}
51113+
case 'LoadLocal': {
51114+
const deps = values.get(instr.value.place.identifier.id);
51115+
if (deps != null) {
51116+
values.set(instr.lvalue.identifier.id, deps);
51117+
}
51118+
break;
51119+
}
51120+
case 'ComputedLoad':
51121+
case 'PropertyLoad':
51122+
case 'BinaryExpression':
51123+
case 'TemplateLiteral':
51124+
case 'CallExpression':
51125+
case 'MethodCall': {
51126+
const aggregateDeps = new Set();
51127+
for (const operand of eachInstructionValueOperand(instr.value)) {
51128+
const deps = values.get(operand.identifier.id);
51129+
if (deps != null) {
51130+
for (const dep of deps) {
51131+
aggregateDeps.add(dep);
51132+
}
51133+
}
51134+
}
51135+
if (aggregateDeps.size !== 0) {
51136+
values.set(instr.lvalue.identifier.id, Array.from(aggregateDeps));
51137+
}
51138+
if (instr.value.kind === 'CallExpression' &&
51139+
isSetStateType(instr.value.callee.identifier) &&
51140+
instr.value.args.length === 1 &&
51141+
instr.value.args[0].kind === 'Identifier') {
51142+
const deps = values.get(instr.value.args[0].identifier.id);
51143+
if (deps != null && new Set(deps).size === effectDeps.length) {
51144+
setStateLocations.push(instr.value.callee.loc);
51145+
}
51146+
else {
51147+
return;
51148+
}
51149+
}
51150+
break;
51151+
}
51152+
default: {
51153+
return;
51154+
}
51155+
}
51156+
}
51157+
for (const operand of eachTerminalOperand(block.terminal)) {
51158+
if (values.has(operand.identifier.id)) {
51159+
return;
51160+
}
51161+
}
51162+
seenBlocks.add(block.id);
51163+
}
51164+
for (const loc of setStateLocations) {
51165+
errors.push({
51166+
reason: 'Values derived from props and state should be calculated during render, not in an effect. (https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state)',
51167+
description: null,
51168+
severity: ErrorSeverity.InvalidReact,
51169+
loc,
51170+
suggestions: null,
51171+
});
51172+
}
51173+
}
51174+
5105351175
function run(func, config, fnType, mode, programContext, logger, filename, code) {
5105451176
var _a, _b;
5105551177
const contextIdentifiers = findContextIdentifiers(func);
@@ -51172,6 +51294,9 @@ function runWithEnvironment(func, env) {
5117251294
if (env.config.validateNoSetStateInRender) {
5117351295
validateNoSetStateInRender(hir).unwrap();
5117451296
}
51297+
if (env.config.validateNoDerivedComputationsInEffects) {
51298+
validateNoDerivedComputationsInEffects(hir);
51299+
}
5117551300
if (env.config.validateNoSetStateInEffects) {
5117651301
env.logErrors(validateNoSetStateInEffects(hir));
5117751302
}
@@ -51194,12 +51319,6 @@ function runWithEnvironment(func, env) {
5119451319
name: 'RewriteInstructionKindsBasedOnReassignment',
5119551320
value: hir,
5119651321
});
51197-
propagatePhiTypes(hir);
51198-
log({
51199-
kind: 'hir',
51200-
name: 'PropagatePhiTypes',
51201-
value: hir,
51202-
});
5120351322
if (env.isInferredMemoEnabled) {
5120451323
if (env.config.validateStaticComponents) {
5120551324
env.logErrors(validateStaticComponents(hir));

compiled/facebook-www/REVISION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
ddf8bc3fbac7aefbf557e2e4a3e14d8de1b80872
1+
99fd4f2ac1fc9bd6b7aeb57afb2bcb1599ad1165
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
ddf8bc3fbac7aefbf557e2e4a3e14d8de1b80872
1+
99fd4f2ac1fc9bd6b7aeb57afb2bcb1599ad1165

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1434,7 +1434,7 @@ __DEV__ &&
14341434
exports.useTransition = function () {
14351435
return resolveDispatcher().useTransition();
14361436
};
1437-
exports.version = "19.2.0-www-classic-ddf8bc3f-20250801";
1437+
exports.version = "19.2.0-www-classic-99fd4f2a-20250805";
14381438
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
14391439
"function" ===
14401440
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
@@ -1434,7 +1434,7 @@ __DEV__ &&
14341434
exports.useTransition = function () {
14351435
return resolveDispatcher().useTransition();
14361436
};
1437-
exports.version = "19.2.0-www-modern-ddf8bc3f-20250801";
1437+
exports.version = "19.2.0-www-modern-99fd4f2a-20250805";
14381438
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
14391439
"function" ===
14401440
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
@@ -610,4 +610,4 @@ exports.useSyncExternalStore = function (
610610
exports.useTransition = function () {
611611
return ReactSharedInternals.H.useTransition();
612612
};
613-
exports.version = "19.2.0-www-classic-ddf8bc3f-20250801";
613+
exports.version = "19.2.0-www-classic-99fd4f2a-20250805";

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,4 +610,4 @@ exports.useSyncExternalStore = function (
610610
exports.useTransition = function () {
611611
return ReactSharedInternals.H.useTransition();
612612
};
613-
exports.version = "19.2.0-www-modern-ddf8bc3f-20250801";
613+
exports.version = "19.2.0-www-modern-99fd4f2a-20250805";

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -614,7 +614,7 @@ exports.useSyncExternalStore = function (
614614
exports.useTransition = function () {
615615
return ReactSharedInternals.H.useTransition();
616616
};
617-
exports.version = "19.2.0-www-classic-ddf8bc3f-20250801";
617+
exports.version = "19.2.0-www-classic-99fd4f2a-20250805";
618618
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
619619
"function" ===
620620
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
@@ -614,7 +614,7 @@ exports.useSyncExternalStore = function (
614614
exports.useTransition = function () {
615615
return ReactSharedInternals.H.useTransition();
616616
};
617-
exports.version = "19.2.0-www-modern-ddf8bc3f-20250801";
617+
exports.version = "19.2.0-www-modern-99fd4f2a-20250805";
618618
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
619619
"function" ===
620620
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
@@ -19318,10 +19318,10 @@ __DEV__ &&
1931819318
(function () {
1931919319
var internals = {
1932019320
bundleType: 1,
19321-
version: "19.2.0-www-classic-ddf8bc3f-20250801",
19321+
version: "19.2.0-www-classic-99fd4f2a-20250805",
1932219322
rendererPackageName: "react-art",
1932319323
currentDispatcherRef: ReactSharedInternals,
19324-
reconcilerVersion: "19.2.0-www-classic-ddf8bc3f-20250801"
19324+
reconcilerVersion: "19.2.0-www-classic-99fd4f2a-20250805"
1932519325
};
1932619326
internals.overrideHookState = overrideHookState;
1932719327
internals.overrideHookStateDeletePath = overrideHookStateDeletePath;
@@ -19355,7 +19355,7 @@ __DEV__ &&
1935519355
exports.Shape = Shape;
1935619356
exports.Surface = Surface;
1935719357
exports.Text = Text;
19358-
exports.version = "19.2.0-www-classic-ddf8bc3f-20250801";
19358+
exports.version = "19.2.0-www-classic-99fd4f2a-20250805";
1935919359
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
1936019360
"function" ===
1936119361
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

0 commit comments

Comments
 (0)