Skip to content

Commit b078c81

Browse files
authored
[Fiber] Replace setCurrentDebugFiberInDEV with runWithFiberInDEV (#29221)
Stacked on #29044. To work with `console.createTask(...).run(...)` we need to be able to run a function in the scope of the task. The main concern with this, other than general performance, is that it might add more stack frames on very deep stacks that hit the stack limit. Such as with the commit phase where we recursively go down the tree. These callbacks aren't really necessary in the recursive part but only in the shallow invocation of the commit phase for each tag. So we could refactor the commit phase so that only the shallow part at each level is covered this way.
1 parent d6cfa0f commit b078c81

File tree

7 files changed

+342
-223
lines changed

7 files changed

+342
-223
lines changed

packages/react-reconciler/src/ReactChildFiber.js

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,7 @@ import {createThenableState, trackUsedThenable} from './ReactFiberThenable';
6363
import {readContextDuringReconciliation} from './ReactFiberNewContext';
6464
import {callLazyInitInDEV} from './ReactFiberCallUserSpace';
6565

66-
import {
67-
getCurrentFiber as getCurrentDebugFiberInDEV,
68-
setCurrentFiber as setCurrentDebugFiberInDEV,
69-
} from './ReactCurrentFiber';
66+
import {runWithFiberInDEV} from './ReactCurrentFiber';
7067

7168
// This tracks the thenables that are unwrapped during reconcilation.
7269
let thenableState: ThenableState | null = null;
@@ -182,15 +179,14 @@ if (__DEV__) {
182179
const fiber = createFiberFromElement((child: any), returnFiber.mode, 0);
183180
fiber.return = returnFiber;
184181

185-
const prevDebugFiber = getCurrentDebugFiberInDEV();
186-
setCurrentDebugFiberInDEV(fiber);
187-
console.error(
188-
'Each child in a list should have a unique "key" prop.' +
189-
'%s%s See https://react.dev/link/warning-keys for more information.',
190-
currentComponentErrorInfo,
191-
childOwnerAppendix,
192-
);
193-
setCurrentDebugFiberInDEV(prevDebugFiber);
182+
runWithFiberInDEV(fiber, () => {
183+
console.error(
184+
'Each child in a list should have a unique "key" prop.' +
185+
'%s%s See https://react.dev/link/warning-keys for more information.',
186+
currentComponentErrorInfo,
187+
childOwnerAppendix,
188+
);
189+
});
194190
};
195191
}
196192

@@ -213,14 +209,17 @@ function validateFragmentProps(
213209
fiber = createFiberFromElement(element, returnFiber.mode, 0);
214210
fiber.return = returnFiber;
215211
}
216-
const prevDebugFiber = getCurrentDebugFiberInDEV();
217-
setCurrentDebugFiberInDEV(fiber);
218-
console.error(
219-
'Invalid prop `%s` supplied to `React.Fragment`. ' +
220-
'React.Fragment can only have `key` and `children` props.',
212+
runWithFiberInDEV(
213+
fiber,
214+
erroredKey => {
215+
console.error(
216+
'Invalid prop `%s` supplied to `React.Fragment`. ' +
217+
'React.Fragment can only have `key` and `children` props.',
218+
erroredKey,
219+
);
220+
},
221221
key,
222222
);
223-
setCurrentDebugFiberInDEV(prevDebugFiber);
224223
break;
225224
}
226225
}
@@ -232,10 +231,9 @@ function validateFragmentProps(
232231
fiber = createFiberFromElement(element, returnFiber.mode, 0);
233232
fiber.return = returnFiber;
234233
}
235-
const prevDebugFiber = getCurrentDebugFiberInDEV();
236-
setCurrentDebugFiberInDEV(fiber);
237-
console.error('Invalid attribute `ref` supplied to `React.Fragment`.');
238-
setCurrentDebugFiberInDEV(prevDebugFiber);
234+
runWithFiberInDEV(fiber, () => {
235+
console.error('Invalid attribute `ref` supplied to `React.Fragment`.');
236+
});
239237
}
240238
}
241239
}

packages/react-reconciler/src/ReactCurrentFiber.js

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -61,16 +61,29 @@ function getCurrentFiberStackInDev(): string {
6161
return '';
6262
}
6363

64-
export function resetCurrentDebugFiberInDEV() {
65-
if (__DEV__) {
66-
resetCurrentFiber();
67-
}
68-
}
69-
70-
export function setCurrentDebugFiberInDEV(fiber: Fiber | null) {
64+
export function runWithFiberInDEV<A0, A1, A2, A3, A4, T>(
65+
fiber: null | Fiber,
66+
callback: (A0, A1, A2, A3, A4) => T,
67+
arg0: A0,
68+
arg1: A1,
69+
arg2: A2,
70+
arg3: A3,
71+
arg4: A4,
72+
): T {
7173
if (__DEV__) {
74+
const previousFiber = current;
7275
setCurrentFiber(fiber);
76+
try {
77+
return callback(arg0, arg1, arg2, arg3, arg4);
78+
} finally {
79+
current = previousFiber;
80+
}
7381
}
82+
// These errors should never make it into a build so we don't need to encode them in codes.json
83+
// eslint-disable-next-line react-internal/prod-error-codes
84+
throw new Error(
85+
'runWithFiberInDEV should never be called in production. This is a bug in React.',
86+
);
7487
}
7588

7689
export function resetCurrentFiber() {
@@ -90,13 +103,6 @@ export function setCurrentFiber(fiber: Fiber | null) {
90103
current = fiber;
91104
}
92105

93-
export function getCurrentFiber(): Fiber | null {
94-
if (__DEV__) {
95-
return current;
96-
}
97-
return null;
98-
}
99-
100106
export function setIsRendering(rendering: boolean) {
101107
if (__DEV__) {
102108
isRendering = rendering;

0 commit comments

Comments
 (0)