Files
react/packages/react-reconciler/src/ReactCurrentFiber.js
T
Sebastian Markbåge 433068eece Remove top stack frame from getCurrentStack (#30306)
The full stack is the current execution stack (`new Error().stack`) +
the current owner stack (`React.captureOwnerStack()`).

The idea with the top frame was that when we append it to console.error
we'd include both since otherwise the true reason would be obscured
behind the little `>` to expand. So we'd just put both stack front and
center. By adding this into getCurrentStack it was easy to use the same
filtering. I never implemented in Fizz or Flight though.

However, with the public API `React.captureOwnerStack()` it's not
necessary to include the current stack since you already have it and
you'd have filtering capabilities in user space too.

Since I'm removing the component stacks from React itself we no longer
need this. It's expected that maybe RDT or framework polyfill would
include this same technique though.
2024-07-11 18:34:41 -04:00

113 lines
2.8 KiB
JavaScript

/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
import type {Fiber} from './ReactInternalTypes';
import ReactSharedInternals from 'shared/ReactSharedInternals';
import {
getStackByFiberInDevAndProd,
getOwnerStackByFiberInDev,
} from './ReactFiberComponentStack';
import {getComponentNameFromOwner} from 'react-reconciler/src/getComponentNameFromFiber';
import {enableOwnerStacks} from 'shared/ReactFeatureFlags';
export let current: Fiber | null = null;
export let isRendering: boolean = false;
export function getCurrentFiberOwnerNameInDevOrNull(): string | null {
if (__DEV__) {
if (current === null) {
return null;
}
const owner = current._debugOwner;
if (owner != null) {
return getComponentNameFromOwner(owner);
}
}
return null;
}
function getCurrentFiberStackInDev(): string {
if (__DEV__) {
if (current === null) {
return '';
}
// Safe because if current fiber exists, we are reconciling,
// and it is guaranteed to be the work-in-progress version.
// TODO: The above comment is not actually true. We might be
// in a commit phase or preemptive set state callback.
if (enableOwnerStacks) {
return getOwnerStackByFiberInDev(current);
}
return getStackByFiberInDevAndProd(current);
}
return '';
}
export function runWithFiberInDEV<A0, A1, A2, A3, A4, T>(
fiber: null | Fiber,
callback: (A0, A1, A2, A3, A4) => T,
arg0: A0,
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
): T {
if (__DEV__) {
const previousFiber = current;
setCurrentFiber(fiber);
try {
if (enableOwnerStacks) {
if (fiber !== null && fiber._debugTask) {
return fiber._debugTask.run(
callback.bind(null, arg0, arg1, arg2, arg3, arg4),
);
}
}
return callback(arg0, arg1, arg2, arg3, arg4);
} finally {
current = previousFiber;
}
}
// These errors should never make it into a build so we don't need to encode them in codes.json
// eslint-disable-next-line react-internal/prod-error-codes
throw new Error(
'runWithFiberInDEV should never be called in production. This is a bug in React.',
);
}
export function resetCurrentFiber() {
if (__DEV__) {
ReactSharedInternals.getCurrentStack = null;
isRendering = false;
}
current = null;
}
export function setCurrentFiber(fiber: Fiber | null) {
if (__DEV__) {
ReactSharedInternals.getCurrentStack =
fiber === null ? null : getCurrentFiberStackInDev;
isRendering = false;
}
current = fiber;
}
export function setIsRendering(rendering: boolean) {
if (__DEV__) {
isRendering = rendering;
}
}
export function getIsRendering(): void | boolean {
if (__DEV__) {
return isRendering;
}
}