Skip to content

Commit

Permalink
[Fiber] Stash ThenableState on the Dependencies Object for Use By Dev…
Browse files Browse the repository at this point in the history
…Tools (#30866)

This lets us track what a Component might suspend on from DevTools. We
could already collect this by replaying a component's Hooks but that
would be expensive to collect from a whole tree.

The thenables themselves might contain useful information but mainly
we'd want access to the `_debugInfo` on the thenables which might
contain additional information from the server.


https://github.com/facebook/react/blob/19bd26beb689e554fceb0b929dc5199be8cba594/packages/shared/ReactTypes.js#L114

In a follow up we should really do something similar in Flight to
transfer `use()` on the debugInfo of that Server Component.
  • Loading branch information
sebmarkbage authored Sep 3, 2024
1 parent e0a07e9 commit 8d68da3
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 17 deletions.
28 changes: 20 additions & 8 deletions packages/react-reconciler/src/ReactFiber.js
Original file line number Diff line number Diff line change
Expand Up @@ -404,10 +404,16 @@ export function createWorkInProgress(current: Fiber, pendingProps: any): Fiber {
workInProgress.dependencies =
currentDependencies === null
? null
: {
lanes: currentDependencies.lanes,
firstContext: currentDependencies.firstContext,
};
: __DEV__
? {
lanes: currentDependencies.lanes,
firstContext: currentDependencies.firstContext,
_debugThenableState: currentDependencies._debugThenableState,
}
: {
lanes: currentDependencies.lanes,
firstContext: currentDependencies.firstContext,
};

// These will be overridden during the parent's reconciliation
workInProgress.sibling = current.sibling;
Expand Down Expand Up @@ -503,10 +509,16 @@ export function resetWorkInProgress(
workInProgress.dependencies =
currentDependencies === null
? null
: {
lanes: currentDependencies.lanes,
firstContext: currentDependencies.firstContext,
};
: __DEV__
? {
lanes: currentDependencies.lanes,
firstContext: currentDependencies.firstContext,
_debugThenableState: currentDependencies._debugThenableState,
}
: {
lanes: currentDependencies.lanes,
firstContext: currentDependencies.firstContext,
};

if (enableProfilerTimer) {
// Note: We don't reset the actualTime counts. It's useful to accumulate
Expand Down
12 changes: 12 additions & 0 deletions packages/react-reconciler/src/ReactFiberHooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,18 @@ function finishRenderingHooks<Props, SecondArg>(
): void {
if (__DEV__) {
workInProgress._debugHookTypes = hookTypesDev;
// Stash the thenable state for use by DevTools.
if (workInProgress.dependencies === null) {
if (thenableState !== null) {
workInProgress.dependencies = {
lanes: NoLanes,
firstContext: null,
_debugThenableState: thenableState,
};
}
} else {
workInProgress.dependencies._debugThenableState = thenableState;
}
}

// We can assume the previous dispatcher is always this one, since we set it
Expand Down
28 changes: 20 additions & 8 deletions packages/react-reconciler/src/ReactFiberNewContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -825,10 +825,16 @@ function readContextForConsumer_withSelect<C>(

// This is the first dependency for this component. Create a new list.
lastContextDependency = contextItem;
consumer.dependencies = {
lanes: NoLanes,
firstContext: contextItem,
};
consumer.dependencies = __DEV__
? {
lanes: NoLanes,
firstContext: contextItem,
_debugThenableState: null,
}
: {
lanes: NoLanes,
firstContext: contextItem,
};
if (enableLazyContextPropagation) {
consumer.flags |= NeedsPropagation;
}
Expand Down Expand Up @@ -869,10 +875,16 @@ function readContextForConsumer<C>(

// This is the first dependency for this component. Create a new list.
lastContextDependency = contextItem;
consumer.dependencies = {
lanes: NoLanes,
firstContext: contextItem,
};
consumer.dependencies = __DEV__
? {
lanes: NoLanes,
firstContext: contextItem,
_debugThenableState: null,
}
: {
lanes: NoLanes,
firstContext: contextItem,
};
if (enableLazyContextPropagation) {
consumer.flags |= NeedsPropagation;
}
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 @@ -37,6 +37,7 @@ import type {
} from './ReactFiberTracingMarkerComponent';
import type {ConcurrentUpdate} from './ReactFiberConcurrentUpdates';
import type {ComponentStackNode} from 'react-server/src/ReactFizzComponentStack';
import type {ThenableState} from './ReactFiberThenable';

// Unwind Circular: moved from ReactFiberHooks.old
export type HookType =
Expand Down Expand Up @@ -81,7 +82,7 @@ export type Dependencies = {
| ContextDependency<mixed>
| ContextDependencyWithSelect<mixed>
| null,
...
_debugThenableState?: null | ThenableState, // DEV-only
};

export type MemoCache = {
Expand Down

0 comments on commit 8d68da3

Please sign in to comment.