Skip to content

Commit

Permalink
Since debugOwner can now be a non-Fiber, fix up places that assumes i…
Browse files Browse the repository at this point in the history
…t is

I left DevTools and ReactNativeFiberInspector to ignore them for now.
  • Loading branch information
sebmarkbage committed Apr 5, 2024
1 parent b44d302 commit d8e167a
Show file tree
Hide file tree
Showing 12 changed files with 119 additions and 125 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,7 @@ import {
import {disableLogs, reenableLogs} from './DevToolsConsolePatching';

let prefix;
export function describeBuiltInComponentFrame(
name: string,
ownerFn: void | null | Function,
): string {
export function describeBuiltInComponentFrame(name: string): string {
if (prefix === undefined) {
// Extract the VM specific prefix used by each line.
try {
Expand All @@ -51,10 +48,7 @@ export function describeBuiltInComponentFrame(
}

export function describeDebugInfoFrame(name: string, env: ?string): string {
return describeBuiltInComponentFrame(
name + (env ? ' (' + env + ')' : ''),
null,
);
return describeBuiltInComponentFrame(name + (env ? ' (' + env + ')' : ''));
}

let reentry = false;
Expand Down Expand Up @@ -292,15 +286,13 @@ export function describeNativeComponentFrame(

export function describeClassComponentFrame(
ctor: Function,
ownerFn: void | null | Function,
currentDispatcherRef: CurrentDispatcherRef,
): string {
return describeNativeComponentFrame(ctor, true, currentDispatcherRef);
}

export function describeFunctionComponentFrame(
fn: Function,
ownerFn: void | null | Function,
currentDispatcherRef: CurrentDispatcherRef,
): string {
return describeNativeComponentFrame(fn, false, currentDispatcherRef);
Expand All @@ -313,7 +305,6 @@ function shouldConstruct(Component: Function) {

export function describeUnknownElementTypeFrameInDEV(
type: any,
ownerFn: void | null | Function,
currentDispatcherRef: CurrentDispatcherRef,
): string {
if (!__DEV__) {
Expand All @@ -330,31 +321,29 @@ export function describeUnknownElementTypeFrameInDEV(
);
}
if (typeof type === 'string') {
return describeBuiltInComponentFrame(type, ownerFn);
return describeBuiltInComponentFrame(type);
}
switch (type) {
case SUSPENSE_NUMBER:
case SUSPENSE_SYMBOL_STRING:
return describeBuiltInComponentFrame('Suspense', ownerFn);
return describeBuiltInComponentFrame('Suspense');
case SUSPENSE_LIST_NUMBER:
case SUSPENSE_LIST_SYMBOL_STRING:
return describeBuiltInComponentFrame('SuspenseList', ownerFn);
return describeBuiltInComponentFrame('SuspenseList');
}
if (typeof type === 'object') {
switch (type.$$typeof) {
case FORWARD_REF_NUMBER:
case FORWARD_REF_SYMBOL_STRING:
return describeFunctionComponentFrame(
type.render,
ownerFn,
currentDispatcherRef,
);
case MEMO_NUMBER:
case MEMO_SYMBOL_STRING:
// Memo may contain any component type so we recursively resolve it.
return describeUnknownElementTypeFrameInDEV(
type.type,
ownerFn,
currentDispatcherRef,
);
case LAZY_NUMBER:
Expand All @@ -366,7 +355,6 @@ export function describeUnknownElementTypeFrameInDEV(
// Lazy may contain any component type so we recursively resolve it.
return describeUnknownElementTypeFrameInDEV(
init(payload),
ownerFn,
currentDispatcherRef,
);
} catch (x) {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,38 +39,30 @@ export function describeFiber(
ClassComponent,
} = workTagMap;

const owner: null | Function = __DEV__
? workInProgress._debugOwner
? workInProgress._debugOwner.type
: null
: null;
switch (workInProgress.tag) {
case HostComponent:
return describeBuiltInComponentFrame(workInProgress.type, owner);
return describeBuiltInComponentFrame(workInProgress.type);
case LazyComponent:
return describeBuiltInComponentFrame('Lazy', owner);
return describeBuiltInComponentFrame('Lazy');
case SuspenseComponent:
return describeBuiltInComponentFrame('Suspense', owner);
return describeBuiltInComponentFrame('Suspense');
case SuspenseListComponent:
return describeBuiltInComponentFrame('SuspenseList', owner);
return describeBuiltInComponentFrame('SuspenseList');
case FunctionComponent:
case IndeterminateComponent:
case SimpleMemoComponent:
return describeFunctionComponentFrame(
workInProgress.type,
owner,
currentDispatcherRef,
);
case ForwardRef:
return describeFunctionComponentFrame(
workInProgress.type.render,
owner,
currentDispatcherRef,
);
case ClassComponent:
return describeClassComponentFrame(
workInProgress.type,
owner,
currentDispatcherRef,
);
default:
Expand Down
53 changes: 35 additions & 18 deletions packages/react-devtools-shared/src/backend/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -1952,15 +1952,24 @@ export function attach(
const {key} = fiber;
const displayName = getDisplayNameForFiber(fiber);
const elementType = getElementTypeForFiber(fiber);
const {_debugOwner} = fiber;
const debugOwner = fiber._debugOwner;

// Ideally we should call getFiberIDThrows() for _debugOwner,
// since owners are almost always higher in the tree (and so have already been processed),
// but in some (rare) instances reported in open source, a descendant mounts before an owner.
// Since this is a DEV only field it's probably okay to also just lazily generate and ID here if needed.
// See https://github.com/facebook/react/issues/21445
const ownerID =
_debugOwner != null ? getOrGenerateFiberID(_debugOwner) : 0;
let ownerID: number;
if (debugOwner != null) {
if (typeof debugOwner.tag === 'number') {
ownerID = getOrGenerateFiberID((debugOwner: any));
} else {
// TODO: Track Server Component Owners.
ownerID = 0;
}
} else {
ownerID = 0;
}
const parentID = parentFiber ? getFiberIDThrows(parentFiber) : 0;

const displayNameStringID = getStringID(displayName);
Expand Down Expand Up @@ -3104,15 +3113,17 @@ export function attach(
return null;
}

const {_debugOwner} = fiber;

const owners: Array<SerializedElement> = [fiberToSerializedElement(fiber)];

if (_debugOwner) {
let owner: null | Fiber = _debugOwner;
while (owner !== null) {
owners.unshift(fiberToSerializedElement(owner));
owner = owner._debugOwner || null;
let owner = fiber._debugOwner;
while (owner != null) {
if (typeof owner.tag === 'number') {
const ownerFiber: Fiber = (owner: any); // Refined
owners.unshift(fiberToSerializedElement(ownerFiber));
owner = ownerFiber._debugOwner;
} else {
// TODO: Track Server Component Owners.
break;
}
}

Expand Down Expand Up @@ -3173,7 +3184,7 @@ export function attach(
}

const {
_debugOwner,
_debugOwner: debugOwner,
stateNode,
key,
memoizedProps,
Expand Down Expand Up @@ -3300,13 +3311,19 @@ export function attach(
context = {value: context};
}

let owners = null;
if (_debugOwner) {
owners = ([]: Array<SerializedElement>);
let owner: null | Fiber = _debugOwner;
while (owner !== null) {
owners.push(fiberToSerializedElement(owner));
owner = owner._debugOwner || null;
let owners: null | Array<SerializedElement> = null;
let owner = debugOwner;
while (owner != null) {
if (typeof owner.tag === 'number') {
const ownerFiber: Fiber = (owner: any); // Refined
if (owners === null) {
owners = [];
}
owners.push(fiberToSerializedElement(ownerFiber));
owner = ownerFiber._debugOwner;
} else {
// TODO: Track Server Component Owners.
break;
}
}
Expand Down
26 changes: 18 additions & 8 deletions packages/react-native-renderer/src/ReactNativeFiberInspector.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,21 @@ function getInspectorDataForInstance(
}

const fiber = findCurrentFiberUsingSlowPath(closestInstance);
if (fiber === null) {
// Might not be currently mounted.
return {
hierarchy: [],
props: emptyObject,
selectedIndex: null,
componentStack: '',
};
}
const fiberHierarchy = getOwnerHierarchy(fiber);
const instance = lastNonHostInstance(fiberHierarchy);
const hierarchy = createHierarchy(fiberHierarchy);
const props = getHostProps(instance);
const selectedIndex = fiberHierarchy.indexOf(instance);
const componentStack =
fiber !== null ? getStackByFiberInDevAndProd(fiber) : '';
const componentStack = getStackByFiberInDevAndProd(fiber);

return {
closestInstance: instance,
Expand All @@ -125,7 +133,7 @@ function getInspectorDataForInstance(
);
}

function getOwnerHierarchy(instance: any) {
function getOwnerHierarchy(instance: Fiber) {
const hierarchy: Array<$FlowFixMe> = [];
traverseOwnerTreeUp(hierarchy, instance);
return hierarchy;
Expand All @@ -143,15 +151,17 @@ function lastNonHostInstance(hierarchy) {
return hierarchy[0];
}

// $FlowFixMe[missing-local-annot]
function traverseOwnerTreeUp(
hierarchy: Array<$FlowFixMe>,
instance: any,
instance: Fiber,
): void {
if (__DEV__ || enableGetInspectorDataForInstanceInProduction) {
if (instance) {
hierarchy.unshift(instance);
traverseOwnerTreeUp(hierarchy, instance._debugOwner);
hierarchy.unshift(instance);
const owner = instance._debugOwner;
if (owner != null && typeof owner.tag === 'number') {
traverseOwnerTreeUp(hierarchy, (owner: any));
} else {
// TODO: Traverse Server Components owners.
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions packages/react-reconciler/src/ReactCurrentFiber.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import type {Fiber} from './ReactInternalTypes';

import ReactSharedInternals from 'shared/ReactSharedInternals';
import {getStackByFiberInDevAndProd} from './ReactFiberComponentStack';
import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';
import {getComponentNameFromOwner} from 'react-reconciler/src/getComponentNameFromFiber';

const ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;

Expand All @@ -24,8 +24,8 @@ export function getCurrentFiberOwnerNameInDevOrNull(): string | null {
return null;
}
const owner = current._debugOwner;
if (owner !== null && typeof owner !== 'undefined') {
return getComponentNameFromFiber(owner);
if (owner != null) {
return getComponentNameFromOwner(owner);
}
}
return null;
Expand Down
7 changes: 4 additions & 3 deletions packages/react-reconciler/src/ReactFiber.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ import {
TracingMarkerComponent,
} from './ReactWorkTags';
import {OffscreenVisible} from './ReactFiberActivityComponent';
import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';
import {getComponentNameFromOwner} from 'react-reconciler/src/getComponentNameFromFiber';
import {isDevToolsPresent} from './ReactFiberDevToolsHook';
import {
resolveClassForHotReloading,
Expand Down Expand Up @@ -110,6 +110,7 @@ import {
attachOffscreenInstance,
} from './ReactFiberCommitWork';
import {getHostContext} from './ReactFiberHostContext';
import type {ReactComponentInfo} from '../../shared/ReactTypes';

export type {Fiber};

Expand Down Expand Up @@ -475,7 +476,7 @@ export function createFiberFromTypeAndProps(
type: any, // React$ElementType
key: null | string,
pendingProps: any,
owner: null | Fiber,
owner: null | ReactComponentInfo | Fiber,
mode: TypeOfMode,
lanes: Lanes,
): Fiber {
Expand Down Expand Up @@ -610,7 +611,7 @@ export function createFiberFromTypeAndProps(
"it's defined in, or you might have mixed up default and " +
'named imports.';
}
const ownerName = owner ? getComponentNameFromFiber(owner) : null;
const ownerName = owner ? getComponentNameFromOwner(owner) : null;
if (ownerName) {
info += '\n\nCheck the render method of `' + ownerName + '`.';
}
Expand Down
19 changes: 7 additions & 12 deletions packages/react-reconciler/src/ReactFiberComponentStack.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,29 +29,24 @@ import {
} from 'shared/ReactComponentStackFrame';

function describeFiber(fiber: Fiber): string {
const owner: null | Function = __DEV__
? fiber._debugOwner
? fiber._debugOwner.type
: null
: null;
switch (fiber.tag) {
case HostHoistable:
case HostSingleton:
case HostComponent:
return describeBuiltInComponentFrame(fiber.type, owner);
return describeBuiltInComponentFrame(fiber.type);
case LazyComponent:
return describeBuiltInComponentFrame('Lazy', owner);
return describeBuiltInComponentFrame('Lazy');
case SuspenseComponent:
return describeBuiltInComponentFrame('Suspense', owner);
return describeBuiltInComponentFrame('Suspense');
case SuspenseListComponent:
return describeBuiltInComponentFrame('SuspenseList', owner);
return describeBuiltInComponentFrame('SuspenseList');
case FunctionComponent:
case SimpleMemoComponent:
return describeFunctionComponentFrame(fiber.type, owner);
return describeFunctionComponentFrame(fiber.type);
case ForwardRef:
return describeFunctionComponentFrame(fiber.type.render, owner);
return describeFunctionComponentFrame(fiber.type.render);
case ClassComponent:
return describeClassComponentFrame(fiber.type, owner);
return describeClassComponentFrame(fiber.type);
default:
return '';
}
Expand Down
3 changes: 2 additions & 1 deletion packages/react-reconciler/src/ReactInternalTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import type {
Usable,
ReactFormState,
Awaited,
ReactComponentInfo,
ReactDebugInfo,
} from 'shared/ReactTypes';
import type {WorkTag} from './ReactWorkTags';
Expand Down Expand Up @@ -193,7 +194,7 @@ export type Fiber = {
// __DEV__ only

_debugInfo?: ReactDebugInfo | null,
_debugOwner?: Fiber | null,
_debugOwner?: ReactComponentInfo | Fiber | null,
_debugIsCurrentlyTiming?: boolean,
_debugNeedsRemount?: boolean,

Expand Down
Loading

0 comments on commit d8e167a

Please sign in to comment.