1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ */
9
+
10
+import type {Source} from 'shared/ReactElementType';
11
+import type {
12
+ RefObject,
13
+ ReactEventResponder,
14
+ ReactEventResponderListener,
15
+ ReactEventResponderInstance,
16
+ ReactContext,
17
+ MutableSourceSubscribeFn,
18
+ MutableSourceGetSnapshotFn,
19
+ MutableSource,
20
+} from 'shared/ReactTypes';
21
+import type {
22
+ SuspenseInstance,
23
+ ReactListenerEvent,
24
+} from './ReactFiberHostConfig';
25
+import type {WorkTag} from './ReactWorkTags';
26
+import type {TypeOfMode} from './ReactTypeOfMode';
27
+import type {SideEffectTag} from './ReactSideEffectTags';
28
+import type {ExpirationTime} from './ReactFiberExpirationTime';
29
+// import type {UpdateQueue} from './ReactUpdateQueue.old';
30
+import type {HookType} from './ReactFiberHooks.old';
31
+import type {RootTag} from './ReactRootTags';
32
+import type {TimeoutHandle, NoTimeout} from './ReactFiberHostConfig';
33
+import type {Wakeable} from 'shared/ReactTypes';
34
+import type {Interaction} from 'scheduler/src/Tracing';
35
+import type {
36
+ OpaqueIDType,
37
+ ReactListenerMap,
38
+} from 'react-reconciler/src/ReactFiberHostConfig';
39
+import type {SuspenseConfig, TimeoutConfig} from './ReactFiberSuspenseConfig';
40
+
41
+export type ReactPriorityLevel = 99 | 98 | 97 | 96 | 95 | 90;
42
+
43
+export type ContextDependency<T> = {
44
+ context: ReactContext<T>,
45
+ observedBits: number,
46
+ next: ContextDependency<mixed> | null,
47
+ ...
48
+};
49
+
50
+export type Dependencies = {
51
+ expirationTime: ExpirationTime,
52
+ firstContext: ContextDependency<mixed> | null,
53
+ responders: Map<
54
+ ReactEventResponder<any, any>,
55
+ ReactEventResponderInstance<any, any>,
56
+ > | null,
57
+ ...
58
+};
59
+
60
+// A Fiber is work on a Component that needs to be done or was done. There can
61
+// be more than one per component.
62
+export type Fiber = {|
63
+ // These first fields are conceptually members of an Instance. This used to
64
+ // be split into a separate type and intersected with the other Fiber fields,
65
+ // but until Flow fixes its intersection bugs, we've merged them into a
66
+ // single type.
67
+
68
+ // An Instance is shared between all versions of a component. We can easily
69
+ // break this out into a separate object to avoid copying so much to the
70
+ // alternate versions of the tree. We put this on a single object for now to
71
+ // minimize the number of objects created during the initial render.
72
+
73
+ // Tag identifying the type of fiber.
74
+ tag: WorkTag,
75
+
76
+ // Unique identifier of this child.
77
+ key: null | string,
78
+
79
+ // The value of element.type which is used to preserve the identity during
80
+ // reconciliation of this child.
81
+ elementType: any,
82
+
83
+ // The resolved function/class/ associated with this fiber.
84
+ type: any,
85
+
86
+ // The local state associated with this fiber.
87
+ stateNode: any,
88
+
89
+ // Conceptual aliases
90
+ // parent : Instance -> return The parent happens to be the same as the
91
+ // return fiber since we've merged the fiber and instance.
92
+
93
+ // Remaining fields belong to Fiber
94
+
95
+ // The Fiber to return to after finishing processing this one.
96
+ // This is effectively the parent, but there can be multiple parents (two)
97
+ // so this is only the parent of the thing we're currently processing.
98
+ // It is conceptually the same as the return address of a stack frame.
99
+ return: Fiber | null,
100
+
101
+ // Singly Linked List Tree Structure.
102
+ child: Fiber | null,
103
+ sibling: Fiber | null,
104
+ index: number,
105
+
106
+ // The ref last used to attach this node.
107
+ // I'll avoid adding an owner field for prod and model that as functions.
108
+ ref:
109
+ | null
110
+ | (((handle: mixed) => void) & {_stringRef: ?string, ...})
111
+ | RefObject,
112
+
113
+ // Input is the data coming into process this fiber. Arguments. Props.
114
+ pendingProps: any, // This type will be more specific once we overload the tag.
115
+ memoizedProps: any, // The props used to create the output.
116
+
117
+ // A queue of state updates and callbacks.
118
+ updateQueue: mixed,
119
+
120
+ // The state used to create the output
121
+ memoizedState: any,
122
+
123
+ // Dependencies (contexts, events) for this fiber, if it has any
124
+ dependencies: Dependencies | null,
125
+
126
+ // Bitfield that describes properties about the fiber and its subtree. E.g.
127
+ // the ConcurrentMode flag indicates whether the subtree should be async-by-
128
+ // default. When a fiber is created, it inherits the mode of its
129
+ // parent. Additional flags can be set at creation time, but after that the
130
+ // value should remain unchanged throughout the fiber's lifetime, particularly
131
+ // before its child fibers are created.
132
+ mode: TypeOfMode,
133
+
134
+ // Effect
135
+ effectTag: SideEffectTag,
136
+
137
+ // Singly linked list fast path to the next fiber with side-effects.
138
+ nextEffect: Fiber | null,
139
+
140
+ // The first and last fiber with side-effect within this subtree. This allows
141
+ // us to reuse a slice of the linked list when we reuse the work done within
142
+ // this fiber.
143
+ firstEffect: Fiber | null,
144
+ lastEffect: Fiber | null,
145
+
146
+ // Represents a time in the future by which this work should be completed.
147
+ // Does not include work found in its subtree.
148
+ expirationTime: ExpirationTime,
149
+
150
+ // This is used to quickly determine if a subtree has no pending changes.
151
+ childExpirationTime: ExpirationTime,
152
+
153
+ // This is a pooled version of a Fiber. Every fiber that gets updated will
154
+ // eventually have a pair. There are cases when we can clean up pairs to save
155
+ // memory if we need to.
156
+ alternate: Fiber | null,
157
+
158
+ // Time spent rendering this Fiber and its descendants for the current update.
159
+ // This tells us how well the tree makes use of sCU for memoization.
160
+ // It is reset to 0 each time we render and only updated when we don't bailout.
161
+ // This field is only set when the enableProfilerTimer flag is enabled.
162
+ actualDuration?: number,
163
+
164
+ // If the Fiber is currently active in the "render" phase,
165
+ // This marks the time at which the work began.
166
+ // This field is only set when the enableProfilerTimer flag is enabled.
167
+ actualStartTime?: number,
168
+
169
+ // Duration of the most recent render time for this Fiber.
170
+ // This value is not updated when we bailout for memoization purposes.
171
+ // This field is only set when the enableProfilerTimer flag is enabled.
172
+ selfBaseDuration?: number,
173
+
174
+ // Sum of base times for all descendants of this Fiber.
175
+ // This value bubbles up during the "complete" phase.
176
+ // This field is only set when the enableProfilerTimer flag is enabled.
177
+ treeBaseDuration?: number,
178
+
179
+ // Conceptual aliases
180
+ // workInProgress : Fiber -> alternate The alternate used for reuse happens
181
+ // to be the same as work in progress.
182
+ // __DEV__ only
183
+ _debugID?: number,
184
+ _debugSource?: Source | null,
185
+ _debugOwner?: Fiber | null,
186
+ _debugIsCurrentlyTiming?: boolean,
187
+ _debugNeedsRemount?: boolean,
188
+
189
+ // Used to verify that the order of hooks does not change between renders.
190
+ _debugHookTypes?: Array<HookType> | null,
191
+|};
192
+
193
+export type PendingInteractionMap = Map<ExpirationTime, Set<Interaction>>;
194
+
195
+type BaseFiberRootProperties = {|
196
+ // The type of root (legacy, batched, concurrent, etc.)
197
+ tag: RootTag,
198
+
199
+ // Any additional information from the host associated with this root.
200
+ containerInfo: any,
201
+ // Used only by persistent updates.
202
+ pendingChildren: any,
203
+ // The currently active root fiber. This is the mutable root of the tree.
204
+ current: Fiber,
205
+
206
+ pingCache:
207
+ | WeakMap<Wakeable, Set<ExpirationTime>>
208
+ | Map<Wakeable, Set<ExpirationTime>>
209
+ | null,
210
+
211
+ finishedExpirationTime: ExpirationTime,
212
+ // A finished work-in-progress HostRoot that's ready to be committed.
213
+ finishedWork: Fiber | null,
214
+ // Timeout handle returned by setTimeout. Used to cancel a pending timeout, if
215
+ // it's superseded by a new one.
216
+ timeoutHandle: TimeoutHandle | NoTimeout,
217
+ // Top context object, used by renderSubtreeIntoContainer
218
+ context: Object | null,
219
+ pendingContext: Object | null,
220
+ // Determines if we should attempt to hydrate on the initial mount
221
+ +hydrate: boolean,
222
+ // Node returned by Scheduler.scheduleCallback
223
+ callbackNode: *,
224
+ // Expiration of the callback associated with this root
225
+ callbackExpirationTime: ExpirationTime,
226
+ // Priority of the callback associated with this root
227
+ callbackPriority: ReactPriorityLevel,
228
+ // The earliest pending expiration time that exists in the tree
229
+ firstPendingTime: ExpirationTime,
230
+ // The latest pending expiration time that exists in the tree
231
+ lastPendingTime: ExpirationTime,
232
+ // The earliest suspended expiration time that exists in the tree
233
+ firstSuspendedTime: ExpirationTime,
234
+ // The latest suspended expiration time that exists in the tree
235
+ lastSuspendedTime: ExpirationTime,
236
+ // The next known expiration time after the suspended range
237
+ nextKnownPendingLevel: ExpirationTime,
238
+ // The latest time at which a suspended component pinged the root to
239
+ // render again
240
+ lastPingedTime: ExpirationTime,
241
+ lastExpiredTime: ExpirationTime,
242
+ // Used by useMutableSource hook to avoid tearing within this root
243
+ // when external, mutable sources are read from during render.
244
+ mutableSourceLastPendingUpdateTime: ExpirationTime,
245
+|};
246
+
247
+// The following attributes are only used by interaction tracing builds.
248
+// They enable interactions to be associated with their async work,
249
+// And expose interaction metadata to the React DevTools Profiler plugin.
250
+// Note that these attributes are only defined when the enableSchedulerTracing flag is enabled.
251
+type ProfilingOnlyFiberRootProperties = {|
252
+ interactionThreadID: number,
253
+ memoizedInteractions: Set<Interaction>,
254
+ pendingInteractionMap: PendingInteractionMap,
255
+|};
256
+
257
+export type SuspenseHydrationCallbacks = {
258
+ onHydrated?: (suspenseInstance: SuspenseInstance) => void,
259
+ onDeleted?: (suspenseInstance: SuspenseInstance) => void,
260
+ ...
261
+};
262
+
263
+// The follow fields are only used by enableSuspenseCallback for hydration.
264
+type SuspenseCallbackOnlyFiberRootProperties = {|
265
+ hydrationCallbacks: null | SuspenseHydrationCallbacks,
266
+|};
267
+
268
+// Exported FiberRoot type includes all properties,
269
+// To avoid requiring potentially error-prone :any casts throughout the project.
270
+// Profiling properties are only safe to access in profiling builds (when enableSchedulerTracing is true).
271
+// The types are defined separately within this file to ensure they stay in sync.
272
+// (We don't have to use an inline :any cast when enableSchedulerTracing is disabled.)
273
+export type FiberRoot = {
274
+ ...BaseFiberRootProperties,
275
+ ...ProfilingOnlyFiberRootProperties,
276
+ ...SuspenseCallbackOnlyFiberRootProperties,
277
+ ...
278
+};
279
+
280
+type BasicStateAction<S> = (S => S) | S;
281
+type Dispatch<A> = A => void;
282
+
283
+export type Dispatcher = {|
284
+ readContext<T>(
285
+ context: ReactContext<T>,
286
+ observedBits: void | number | boolean,
287
+ ): T,
288
+ useState<S>(initialState: (() => S) | S): [S, Dispatch<BasicStateAction<S>>],
289
+ useReducer<S, I, A>(
290
+ reducer: (S, A) => S,
291
+ initialArg: I,
292
+ init?: (I) => S,
293
+ ): [S, Dispatch<A>],
294
+ useContext<T>(
295
+ context: ReactContext<T>,
296
+ observedBits: void | number | boolean,
297
+ ): T,
298
+ useRef<T>(initialValue: T): {|current: T|},
299
+ useEffect(
300
+ create: () => (() => void) | void,
301
+ deps: Array<mixed> | void | null,
302
+ ): void,
303
+ useLayoutEffect(
304
+ create: () => (() => void) | void,
305
+ deps: Array<mixed> | void | null,
306
+ ): void,
307
+ useCallback<T>(callback: T, deps: Array<mixed> | void | null): T,
308
+ useMemo<T>(nextCreate: () => T, deps: Array<mixed> | void | null): T,
309
+ useImperativeHandle<T>(
310
+ ref: {|current: T | null|} | ((inst: T | null) => mixed) | null | void,
311
+ create: () => T,
312
+ deps: Array<mixed> | void | null,
313
+ ): void,
314
+ useDebugValue<T>(value: T, formatterFn: ?(value: T) => mixed): void,
315
+ useResponder<E, C>(
316
+ responder: ReactEventResponder<E, C>,
317
+ props: Object,
318
+ ): ReactEventResponderListener<E, C>,
319
+ useDeferredValue<T>(value: T, config: TimeoutConfig | void | null): T,
320
+ useTransition(
321
+ config: SuspenseConfig | void | null,
322
+ ): [(() => void) => void, boolean],
323
+ useMutableSource<Source, Snapshot>(
324
+ source: MutableSource<Source>,
325
+ getSnapshot: MutableSourceGetSnapshotFn<Source, Snapshot>,
326
+ subscribe: MutableSourceSubscribeFn<Source, Snapshot>,
327
+ ): Snapshot,
328
+ useEvent(event: ReactListenerEvent): ReactListenerMap,
329
+ useOpaqueIdentifier(): OpaqueIDType | void,
330
+|};