import {enableViewTransition} from 'shared/ReactFeatureFlags';
import type {Fiber} from './ReactInternalTypes';
import type {ReactComponentInfo} from 'shared/ReactTypes';
import {
HostComponent,
HostHoistable,
HostSingleton,
LazyComponent,
SuspenseComponent,
SuspenseListComponent,
FunctionComponent,
ForwardRef,
SimpleMemoComponent,
ClassComponent,
HostText,
ViewTransitionComponent,
ActivityComponent,
} from './ReactWorkTags';
import {
describeBuiltInComponentFrame,
describeFunctionComponentFrame,
describeClassComponentFrame,
describeDebugInfoFrame,
} from 'shared/ReactComponentStackFrame';
import {formatOwnerStack} from 'shared/ReactOwnerStackFrames';
function describeFiber(fiber: Fiber): string {
switch (fiber.tag) {
case HostHoistable:
case HostSingleton:
case HostComponent:
return describeBuiltInComponentFrame(fiber.type);
case LazyComponent:
return describeBuiltInComponentFrame('Lazy');
case SuspenseComponent:
return describeBuiltInComponentFrame('Suspense');
case SuspenseListComponent:
return describeBuiltInComponentFrame('SuspenseList');
case FunctionComponent:
case SimpleMemoComponent:
return describeFunctionComponentFrame(fiber.type);
case ForwardRef:
return describeFunctionComponentFrame(fiber.type.render);
case ClassComponent:
return describeClassComponentFrame(fiber.type);
case ActivityComponent:
return describeBuiltInComponentFrame('Activity');
case ViewTransitionComponent:
if (enableViewTransition) {
return describeBuiltInComponentFrame('ViewTransition');
}
default:
return '';
}
}
export function getStackByFiberInDevAndProd(workInProgress: Fiber): string {
try {
let info = '';
let node: Fiber = workInProgress;
do {
info += describeFiber(node);
if (__DEV__) {
const debugInfo = node._debugInfo;
if (debugInfo) {
for (let i = debugInfo.length - 1; i >= 0; i--) {
const entry = debugInfo[i];
if (typeof entry.name === 'string') {
info += describeDebugInfoFrame(
entry.name,
entry.env,
entry.debugLocation,
);
}
}
}
}
node = node.return;
} while (node);
return info;
} catch (x) {
return '\nError generating stack: ' + x.message + '\n' + x.stack;
}
}
function describeFunctionComponentFrameWithoutLineNumber(fn: Function): string {
const name = fn ? fn.displayName || fn.name : '';
return name ? describeBuiltInComponentFrame(name) : '';
}
export function getOwnerStackByFiberInDev(workInProgress: Fiber): string {
if (!__DEV__) {
return '';
}
try {
let info = '';
if (workInProgress.tag === HostText) {
workInProgress = (workInProgress.return: any);
}
switch (workInProgress.tag) {
case HostHoistable:
case HostSingleton:
case HostComponent:
info += describeBuiltInComponentFrame(workInProgress.type);
break;
case SuspenseComponent:
info += describeBuiltInComponentFrame('Suspense');
break;
case SuspenseListComponent:
info += describeBuiltInComponentFrame('SuspenseList');
break;
case ActivityComponent:
info += describeBuiltInComponentFrame('Activity');
break;
case ViewTransitionComponent:
if (enableViewTransition) {
info += describeBuiltInComponentFrame('ViewTransition');
break;
}
case FunctionComponent:
case SimpleMemoComponent:
case ClassComponent:
if (!workInProgress._debugOwner && info === '') {
info += describeFunctionComponentFrameWithoutLineNumber(
workInProgress.type,
);
}
break;
case ForwardRef:
if (!workInProgress._debugOwner && info === '') {
info += describeFunctionComponentFrameWithoutLineNumber(
workInProgress.type.render,
);
}
break;
}
let owner: void | null | Fiber | ReactComponentInfo = workInProgress;
while (owner) {
if (typeof owner.tag === 'number') {
const fiber: Fiber = (owner: any);
owner = fiber._debugOwner;
let debugStack = fiber._debugStack;
if (owner && debugStack) {
if (typeof debugStack !== 'string') {
fiber._debugStack = debugStack = formatOwnerStack(debugStack);
}
if (debugStack !== '') {
info += '\n' + debugStack;
}
}
} else if (owner.debugStack != null) {
const ownerStack: Error = owner.debugStack;
owner = owner.owner;
if (owner && ownerStack) {
info += '\n' + formatOwnerStack(ownerStack);
}
} else {
break;
}
}
return info;
} catch (x) {
return '\nError generating stack: ' + x.message + '\n' + x.stack;
}
}