Skip to content

Commit ec7d9a7

Browse files
authored
Resolve the .default export of a React.lazy as the canonical value (#34906)
For debug purposes this is the value that the `React.lazy` resolves to. It also lets us look at that value for descriptions like its name.
1 parent 40c7a7f commit ec7d9a7

File tree

1 file changed

+27
-4
lines changed

1 file changed

+27
-4
lines changed

packages/react/src/ReactLazy.js

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import {enableAsyncDebugInfo} from 'shared/ReactFeatureFlags';
2020

2121
import {REACT_LAZY_TYPE} from 'shared/ReactSymbols';
2222

23+
import noop from 'shared/noop';
24+
2325
const Uninitialized = -1;
2426
const Pending = 0;
2527
const Resolved = 1;
@@ -67,12 +69,20 @@ export type LazyComponent<T, P> = {
6769

6870
function lazyInitializer<T>(payload: Payload<T>): T {
6971
if (payload._status === Uninitialized) {
72+
let resolveDebugValue: (void | T) => void = (null: any);
73+
let rejectDebugValue: mixed => void = (null: any);
7074
if (__DEV__ && enableAsyncDebugInfo) {
7175
const ioInfo = payload._ioInfo;
7276
if (ioInfo != null) {
7377
// Mark when we first kicked off the lazy request.
7478
// $FlowFixMe[cannot-write]
7579
ioInfo.start = ioInfo.end = performance.now();
80+
// Stash a Promise for introspection of the value later.
81+
// $FlowFixMe[cannot-write]
82+
ioInfo.value = new Promise((resolve, reject) => {
83+
resolveDebugValue = resolve;
84+
rejectDebugValue = reject;
85+
});
7686
}
7787
}
7888
const ctor = payload._result;
@@ -92,12 +102,20 @@ function lazyInitializer<T>(payload: Payload<T>): T {
92102
const resolved: ResolvedPayload<T> = (payload: any);
93103
resolved._status = Resolved;
94104
resolved._result = moduleObject;
95-
if (__DEV__) {
105+
if (__DEV__ && enableAsyncDebugInfo) {
96106
const ioInfo = payload._ioInfo;
97107
if (ioInfo != null) {
98108
// Mark the end time of when we resolved.
99109
// $FlowFixMe[cannot-write]
100110
ioInfo.end = performance.now();
111+
// Surface the default export as the resolved "value" for debug purposes.
112+
const debugValue =
113+
moduleObject == null ? undefined : moduleObject.default;
114+
resolveDebugValue(debugValue);
115+
// $FlowFixMe
116+
ioInfo.value.status = 'fulfilled';
117+
// $FlowFixMe
118+
ioInfo.value.value = debugValue;
101119
}
102120
// Make the thenable introspectable
103121
if (thenable.status === undefined) {
@@ -124,6 +142,14 @@ function lazyInitializer<T>(payload: Payload<T>): T {
124142
// Mark the end time of when we rejected.
125143
// $FlowFixMe[cannot-write]
126144
ioInfo.end = performance.now();
145+
// Hide unhandled rejections.
146+
// $FlowFixMe
147+
ioInfo.value.then(noop, noop);
148+
rejectDebugValue(error);
149+
// $FlowFixMe
150+
ioInfo.value.status = 'rejected';
151+
// $FlowFixMe
152+
ioInfo.value.reason = error;
127153
}
128154
// Make the thenable introspectable
129155
if (thenable.status === undefined) {
@@ -139,9 +165,6 @@ function lazyInitializer<T>(payload: Payload<T>): T {
139165
if (__DEV__ && enableAsyncDebugInfo) {
140166
const ioInfo = payload._ioInfo;
141167
if (ioInfo != null) {
142-
// Stash the thenable for introspection of the value later.
143-
// $FlowFixMe[cannot-write]
144-
ioInfo.value = thenable;
145168
const displayName = thenable.displayName;
146169
if (typeof displayName === 'string') {
147170
// $FlowFixMe[cannot-write]

0 commit comments

Comments
 (0)