7
* @flow
8
*/
9
10
-import type {Wakeable, Thenable, ReactDebugInfo} from 'shared/ReactTypes';
10
+import type {
11
+ Wakeable,
12
+ Thenable,
13
+ FulfilledThenable,
14
+ RejectedThenable,
15
+ ReactDebugInfo,
16
+ ReactIOInfo,
17
+} from 'shared/ReactTypes';
18
+
19
+import {enableAsyncDebugInfo} from 'shared/ReactFeatureFlags';
20
21
import {REACT_LAZY_TYPE} from 'shared/ReactSymbols';
22
28
type UninitializedPayload<T> = {
29
_status: -1,
30
_result: () => Thenable<{default: T, ...}>,
31
+ _ioInfo?: ReactIOInfo, // DEV-only
32
};
33
34
type PendingPayload = {
35
_status: 0,
36
_result: Wakeable,
37
+ _ioInfo?: ReactIOInfo, // DEV-only
38
};
39
40
type ResolvedPayload<T> = {
41
_status: 1,
42
_result: {default: T, ...},
43
+ _ioInfo?: ReactIOInfo, // DEV-only
44
};
45
46
type RejectedPayload = {
47
_status: 2,
48
_result: mixed,
49
+ _ioInfo?: ReactIOInfo, // DEV-only
50
};
51
52
type Payload<T> =
64
65
function lazyInitializer<T>(payload: Payload<T>): T {
66
if (payload._status === Uninitialized) {
67
+ if (__DEV__ && enableAsyncDebugInfo) {
68
+ const ioInfo = payload._ioInfo;
69
+ if (ioInfo != null) {
70
+ // Mark when we first kicked off the lazy request.
71
+ // $FlowFixMe[cannot-write]
72
+ ioInfo.start = ioInfo.end = performance.now();
73
+ }
74
+ }
75
const ctor = payload._result;
76
const thenable = ctor();
77
// Transition to the next state.
89
const resolved: ResolvedPayload<T> = (payload: any);
90
resolved._status = Resolved;
91
resolved._result = moduleObject;
92
+ if (__DEV__) {
93
+ const ioInfo = payload._ioInfo;
94
+ if (ioInfo != null) {
95
+ // Mark the end time of when we resolved.
96
+ // $FlowFixMe[cannot-write]
97
+ ioInfo.end = performance.now();
98
+ }
99
+ // Make the thenable introspectable
100
+ if (thenable.status === undefined) {
101
+ const fulfilledThenable: FulfilledThenable<{default: T, ...}> =
102
+ (thenable: any);
103
+ fulfilledThenable.status = 'fulfilled';
104
+ fulfilledThenable.value = moduleObject;
105
+ }
106
+ }
107
}
108
},
109
error => {
115
const rejected: RejectedPayload = (payload: any);
116
rejected._status = Rejected;
117
rejected._result = error;
118
+ if (__DEV__ && enableAsyncDebugInfo) {
119
+ const ioInfo = payload._ioInfo;
120
+ if (ioInfo != null) {
121
+ // Mark the end time of when we rejected.
122
+ // $FlowFixMe[cannot-write]
123
+ ioInfo.end = performance.now();
124
+ }
125
+ // Make the thenable introspectable
126
+ if (thenable.status === undefined) {
127
+ const rejectedThenable: RejectedThenable<{default: T, ...}> =
128
+ (thenable: any);
129
+ rejectedThenable.status = 'rejected';
130
+ rejectedThenable.reason = error;
131
+ }
132
+ }
133
}
134
},
135
);
136
+ if (__DEV__ && enableAsyncDebugInfo) {
137
+ const ioInfo = payload._ioInfo;
138
+ if (ioInfo != null) {
139
+ // Stash the thenable for introspection of the value later.
140
+ // $FlowFixMe[cannot-write]
141
+ ioInfo.value = thenable;
142
+ const displayName = thenable.displayName;
143
+ if (typeof displayName === 'string') {
144
+ // $FlowFixMe[cannot-write]
145
+ ioInfo.name = displayName;
146
+ }
147
+ }
148
+ }
149
if (payload._status === Uninitialized) {
150
// In case, we're still uninitialized, then we're waiting for the thenable
151
// to resolve. Set it as pending in the meantime.
204
_init: lazyInitializer,
205
};
206
207
+ if (__DEV__ && enableAsyncDebugInfo) {
208
+ // TODO: We should really track the owner here but currently ReactIOInfo
209
+ // can only contain ReactComponentInfo and not a Fiber. It's unusual to
210
+ // create a lazy inside an owner though since they should be in module scope.
211
+ const owner = null;
212
+ const ioInfo: ReactIOInfo = {
213
+ name: 'lazy',
214
+ start: -1,
215
+ end: -1,
216
+ value: null,
217
+ owner: owner,
218
+ debugStack: new Error('react-stack-top-frame'),
219
+ // eslint-disable-next-line react-internal/no-production-logging
220
+ debugTask: console.createTask ? console.createTask('lazy()') : null,
221
+ };
222
+ payload._ioInfo = ioInfo;
223
+ // Add debug info to the lazy, but this doesn't have an await stack yet.
224
+ // That will be inferred by later usage.
225
+ lazyType._debugInfo = [{awaited: ioInfo}];
226
+ }
227
+
228
return lazyType;
229
}