| 1 | /** |
| 2 | * Copyright (c) Meta Platforms, Inc. and 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 {ReactOptimisticKey} from './ReactSymbols'; |
| 11 | |
| 12 | export type {ReactOptimisticKey}; |
| 13 | |
| 14 | export type ReactKey = null | string | ReactOptimisticKey; |
| 15 | |
| 16 | export type ReactNode = |
| 17 | | React$Element<any> |
| 18 | | ReactPortal |
| 19 | | ReactText |
| 20 | | ReactFragment |
| 21 | | ReactProvider<any> |
| 22 | | ReactConsumer<any>; |
| 23 | |
| 24 | export type ReactEmpty = null | void | boolean; |
| 25 | |
| 26 | export type ReactFragment = ReactEmpty | Iterable<React$Node>; |
| 27 | |
| 28 | export type ReactNodeList = ReactEmpty | React$Node; |
| 29 | |
| 30 | export type ReactText = string | number; |
| 31 | |
| 32 | export type ReactProvider<T> = { |
| 33 | $$typeof: symbol | number, |
| 34 | type: ReactContext<T>, |
| 35 | key: ReactKey, |
| 36 | ref: null, |
| 37 | props: { |
| 38 | value: T, |
| 39 | children?: ReactNodeList, |
| 40 | }, |
| 41 | }; |
| 42 | |
| 43 | export type ReactConsumerType<T> = { |
| 44 | $$typeof: symbol | number, |
| 45 | _context: ReactContext<T>, |
| 46 | }; |
| 47 | |
| 48 | export type ReactConsumer<T> = { |
| 49 | $$typeof: symbol | number, |
| 50 | type: ReactConsumerType<T>, |
| 51 | key: ReactKey, |
| 52 | ref: null, |
| 53 | props: { |
| 54 | children: (value: T) => ReactNodeList, |
| 55 | }, |
| 56 | }; |
| 57 | |
| 58 | export type ReactContext<T> = { |
| 59 | $$typeof: symbol | number, |
| 60 | Consumer: ReactConsumerType<T>, |
| 61 | Provider: ReactContext<T>, |
| 62 | _currentValue: T, |
| 63 | _currentValue2: T, |
| 64 | _threadCount: number, |
| 65 | // DEV only |
| 66 | _currentRenderer?: Object | null, |
| 67 | _currentRenderer2?: Object | null, |
| 68 | // This value may be added by application code |
| 69 | // to improve DEV tooling display names |
| 70 | displayName?: string, |
| 71 | }; |
| 72 | |
| 73 | export type ReactPortal = { |
| 74 | $$typeof: symbol | number, |
| 75 | key: ReactKey, |
| 76 | containerInfo: any, |
| 77 | children: ReactNodeList, |
| 78 | // TODO: figure out the API for cross-renderer implementation. |
| 79 | implementation: any, |
| 80 | }; |
| 81 | |
| 82 | export type RefObject = { |
| 83 | current: any, |
| 84 | }; |
| 85 | |
| 86 | export type ReactScope = { |
| 87 | $$typeof: symbol | number, |
| 88 | }; |
| 89 | |
| 90 | export type ReactScopeQuery = ( |
| 91 | type: string, |
| 92 | props: {[string]: mixed}, |
| 93 | instance: mixed, |
| 94 | ) => boolean; |
| 95 | |
| 96 | export type ReactScopeInstance = { |
| 97 | DO_NOT_USE_queryAllNodes(ReactScopeQuery): null | Array<Object>, |
| 98 | DO_NOT_USE_queryFirstNode(ReactScopeQuery): null | Object, |
| 99 | containsNode(Object): boolean, |
| 100 | getChildContextValues: <T>(context: ReactContext<T>) => Array<T>, |
| 101 | }; |
| 102 | |
| 103 | // The subset of a Thenable required by things thrown by Suspense. |
| 104 | // This doesn't require a value to be passed to either handler. |
| 105 | export interface Wakeable { |
| 106 | then(onFulfill: () => mixed, onReject: () => mixed): void | Wakeable; |
| 107 | } |
| 108 | |
| 109 | // The subset of a Promise that React APIs rely on. This resolves a value. |
| 110 | // This doesn't require a return value neither from the handler nor the |
| 111 | // then function. |
| 112 | interface ThenableImpl<T> { |
| 113 | then( |
| 114 | onFulfill: (value: T) => mixed, |
| 115 | onReject: (error: mixed) => mixed, |
| 116 | ): void | Wakeable; |
| 117 | displayName?: string; |
| 118 | } |
| 119 | interface UntrackedThenable<T> extends ThenableImpl<T> { |
| 120 | status?: void; |
| 121 | _debugInfo?: null | ReactDebugInfo; |
| 122 | } |
| 123 | |
| 124 | export interface PendingThenable<T> extends ThenableImpl<T> { |
| 125 | status: 'pending'; |
| 126 | _debugInfo?: null | ReactDebugInfo; |
| 127 | } |
| 128 | |
| 129 | export interface WeakPendingThenable<T> extends ThenableImpl<T> { |
| 130 | status: 'pending_weak'; |
| 131 | _debugInfo?: null | ReactDebugInfo; |
| 132 | } |
| 133 | |
| 134 | export interface FulfilledThenable<T> extends ThenableImpl<T> { |
| 135 | status: 'fulfilled'; |
| 136 | value: T; |
| 137 | _debugInfo?: null | ReactDebugInfo; |
| 138 | } |
| 139 | |
| 140 | export interface RejectedThenable<T> extends ThenableImpl<T> { |
| 141 | status: 'rejected'; |
| 142 | reason: mixed; |
| 143 | _debugInfo?: null | ReactDebugInfo; |
| 144 | } |
| 145 | |
| 146 | export type Thenable<T> = |
| 147 | | UntrackedThenable<T> |
| 148 | | PendingThenable<T> |
| 149 | | WeakPendingThenable<T> |
| 150 | | FulfilledThenable<T> |
| 151 | | RejectedThenable<T>; |
| 152 | |
| 153 | export type ReactRecoverableReason = string | (() => mixed); |
| 154 | |
| 155 | // A recoverable lets an intermediate renderer defer a subtree to a downstream |
| 156 | // renderer. It does not produce a value: a renderer either continues through |
| 157 | // it or interrupts the current render so that a later renderer can recover the |
| 158 | // subtree. The reason is initialized only by a renderer that defers the work. |
| 159 | export type ReactRecoverable = { |
| 160 | $$typeof: symbol, |
| 161 | _reason: ReactRecoverableReason | void, |
| 162 | }; |
| 163 | |
| 164 | export type StartTransitionOptions = { |
| 165 | name?: string, |
| 166 | }; |
| 167 | |
| 168 | export type Usable<T> = Thenable<T> | ReactContext<T> | ReactRecoverable; |
| 169 | |
| 170 | export type ReactCustomFormAction = { |
| 171 | name?: string, |
| 172 | action?: string, |
| 173 | encType?: string, |
| 174 | method?: string, |
| 175 | target?: string, |
| 176 | data?: null | FormData, |
| 177 | }; |
| 178 | |
| 179 | // This is an opaque type returned by decodeFormState on the server, but it's |
| 180 | // defined in this shared file because the same type is used by React on |
| 181 | // the client. |
| 182 | export type ReactFormState<S, ReferenceId> = [ |
| 183 | S /* actual state value */, |
| 184 | string /* key path */, |
| 185 | ReferenceId /* Server Reference ID */, |
| 186 | number /* number of bound arguments */, |
| 187 | ]; |
| 188 | |
| 189 | // Intrinsic GestureProvider. This type varies by Environment whether a particular |
| 190 | // renderer supports it. |
| 191 | export type GestureProvider = any; |
| 192 | |
| 193 | export type GestureOptions = { |
| 194 | rangeStart?: number, |
| 195 | rangeEnd?: number, |
| 196 | }; |
| 197 | |
| 198 | export type Awaited<T> = T extends null | void |
| 199 | ? T // special case for `null | undefined` when not in `--strictNullChecks` mode |
| 200 | : T extends Object // `await` only unwraps object types with a callable then. Non-object types are not unwrapped. |
| 201 | ? T extends {then(onfulfilled: infer F): any} // thenable, extracts the first argument to `then()` |
| 202 | ? F extends (value: infer V) => any // if the argument to `then` is callable, extracts the argument |
| 203 | ? Awaited<V> // recursively unwrap the value |
| 204 | : empty // the argument to `then` was not callable. |
| 205 | : T // argument was not an object |
| 206 | : T; // non-thenable |
| 207 | |
| 208 | export type ReactCallSite = [ |
| 209 | string, // function name |
| 210 | string, // file name TODO: model nested eval locations as nested arrays |
| 211 | number, // line number |
| 212 | number, // column number |
| 213 | number, // enclosing line number |
| 214 | number, // enclosing column number |
| 215 | boolean, // async resume |
| 216 | ]; |
| 217 | |
| 218 | export type ReactStackTrace = Array<ReactCallSite>; |
| 219 | |
| 220 | export type ReactFunctionLocation = [ |
| 221 | string, // function name |
| 222 | string, // file name TODO: model nested eval locations as nested arrays |
| 223 | number, // enclosing line number |
| 224 | number, // enclosing column number |
| 225 | ]; |
| 226 | |
| 227 | export type ReactComponentInfo = { |
| 228 | +name: string, |
| 229 | +env?: string, |
| 230 | +key?: ReactKey, |
| 231 | +owner?: null | ReactComponentInfo, |
| 232 | +stack?: null | ReactStackTrace, |
| 233 | +props?: null | {[name: string]: mixed}, |
| 234 | // Stashed Data for the Specific Execution Environment. Not part of the transport protocol |
| 235 | +debugStack?: null | Error, |
| 236 | +debugTask?: null | ConsoleTask, |
| 237 | debugLocation?: null | Error, |
| 238 | }; |
| 239 | |
| 240 | export type ReactEnvironmentInfo = { |
| 241 | +env: string, |
| 242 | }; |
| 243 | |
| 244 | export type ReactErrorInfoProd = { |
| 245 | +digest: string, |
| 246 | }; |
| 247 | |
| 248 | export type JSONValue = |
| 249 | | string |
| 250 | | boolean |
| 251 | | number |
| 252 | | null |
| 253 | | {+[key: string]: JSONValue} |
| 254 | | $ReadOnlyArray<JSONValue>; |
| 255 | |
| 256 | export type ReactErrorInfoDev = { |
| 257 | +digest?: string, |
| 258 | +name: string, |
| 259 | +message: string, |
| 260 | +stack: ReactStackTrace, |
| 261 | +env: string, |
| 262 | +owner?: null | string, |
| 263 | cause?: JSONValue, |
| 264 | errors?: JSONValue, |
| 265 | }; |
| 266 | |
| 267 | export type ReactErrorInfo = ReactErrorInfoProd | ReactErrorInfoDev; |
| 268 | |
| 269 | // The point where the Async Info started which might not be the same place it was awaited. |
| 270 | export type ReactIOInfo = { |
| 271 | +name: string, // the name of the async function being called (e.g. "fetch") |
| 272 | +start: number, // the start time |
| 273 | +end: number, // the end time (this might be different from the time the await was unblocked) |
| 274 | +byteSize?: number, // the byte size of this resource across the network. (should only be included if affecting the client.) |
| 275 | +value?: null | Promise<mixed>, // the Promise that was awaited if any, may be rejected |
| 276 | +env?: string, // the environment where this I/O was spawned. |
| 277 | +owner?: null | ReactComponentInfo, |
| 278 | +stack?: null | ReactStackTrace, |
| 279 | // Stashed Data for the Specific Execution Environment. Not part of the transport protocol |
| 280 | +debugStack?: null | Error, |
| 281 | +debugTask?: null | ConsoleTask, |
| 282 | }; |
| 283 | |
| 284 | export type ReactAsyncInfo = { |
| 285 | +awaited: ReactIOInfo, |
| 286 | +env?: string, // the environment where this was awaited. This might not be the same as where it was spawned. |
| 287 | +owner?: null | ReactComponentInfo, |
| 288 | +stack?: null | ReactStackTrace, |
| 289 | // Stashed Data for the Specific Execution Environment. Not part of the transport protocol |
| 290 | +debugStack?: null | Error, |
| 291 | +debugTask?: null | ConsoleTask, |
| 292 | }; |
| 293 | |
| 294 | export type ReactTimeInfo = { |
| 295 | +time: number, // performance.now |
| 296 | }; |
| 297 | |
| 298 | export type ReactDebugInfoEntry = |
| 299 | | ReactComponentInfo |
| 300 | | ReactEnvironmentInfo |
| 301 | | ReactAsyncInfo |
| 302 | | ReactTimeInfo; |
| 303 | |
| 304 | export type ReactDebugInfo = Array<ReactDebugInfoEntry>; |
| 305 | |
| 306 | // Intrinsic ViewTransitionInstance. This type varies by Environment whether a particular |
| 307 | // renderer supports it. |
| 308 | export type ViewTransitionInstance = any; |
| 309 | |
| 310 | export type ViewTransitionClassPerType = { |
| 311 | [transitionType: 'default' | string]: 'none' | 'auto' | string, |
| 312 | }; |
| 313 | |
| 314 | export type ViewTransitionClass = |
| 315 | | 'none' |
| 316 | | 'auto' |
| 317 | | string |
| 318 | | ViewTransitionClassPerType; |
| 319 | |
| 320 | export type GestureOptionsRequired = { |
| 321 | rangeStart: number, |
| 322 | rangeEnd: number, |
| 323 | }; |
| 324 | |
| 325 | export type ViewTransitionProps = { |
| 326 | name?: string, |
| 327 | children?: ReactNodeList, |
| 328 | default?: ViewTransitionClass, |
| 329 | enter?: ViewTransitionClass, |
| 330 | exit?: ViewTransitionClass, |
| 331 | share?: ViewTransitionClass, |
| 332 | update?: ViewTransitionClass, |
| 333 | parentEnter?: ViewTransitionClass, |
| 334 | parentExit?: ViewTransitionClass, |
| 335 | onEnter?: ( |
| 336 | instance: ViewTransitionInstance, |
| 337 | types: Array<string>, |
| 338 | ) => void | (() => void), |
| 339 | onExit?: ( |
| 340 | instance: ViewTransitionInstance, |
| 341 | types: Array<string>, |
| 342 | ) => void | (() => void), |
| 343 | onParentEnter?: ( |
| 344 | instance: ViewTransitionInstance, |
| 345 | types: Array<string>, |
| 346 | ) => void | (() => void), |
| 347 | onParentExit?: ( |
| 348 | instance: ViewTransitionInstance, |
| 349 | types: Array<string>, |
| 350 | ) => void | (() => void), |
| 351 | onShare?: ( |
| 352 | instance: ViewTransitionInstance, |
| 353 | types: Array<string>, |
| 354 | ) => void | (() => void), |
| 355 | onUpdate?: ( |
| 356 | instance: ViewTransitionInstance, |
| 357 | types: Array<string>, |
| 358 | ) => void | (() => void), |
| 359 | onGestureEnter?: ( |
| 360 | timeline: GestureProvider, |
| 361 | options: GestureOptionsRequired, |
| 362 | instance: ViewTransitionInstance, |
| 363 | types: Array<string>, |
| 364 | ) => void | (() => void), |
| 365 | onGestureExit?: ( |
| 366 | timeline: GestureProvider, |
| 367 | options: GestureOptionsRequired, |
| 368 | instance: ViewTransitionInstance, |
| 369 | types: Array<string>, |
| 370 | ) => void | (() => void), |
| 371 | onGestureParentEnter?: ( |
| 372 | timeline: GestureProvider, |
| 373 | options: GestureOptionsRequired, |
| 374 | instance: ViewTransitionInstance, |
| 375 | types: Array<string>, |
| 376 | ) => void | (() => void), |
| 377 | onGestureParentExit?: ( |
| 378 | timeline: GestureProvider, |
| 379 | options: GestureOptionsRequired, |
| 380 | instance: ViewTransitionInstance, |
| 381 | types: Array<string>, |
| 382 | ) => void | (() => void), |
| 383 | onGestureShare?: ( |
| 384 | timeline: GestureProvider, |
| 385 | options: GestureOptionsRequired, |
| 386 | instance: ViewTransitionInstance, |
| 387 | types: Array<string>, |
| 388 | ) => void | (() => void), |
| 389 | onGestureUpdate?: ( |
| 390 | timeline: GestureProvider, |
| 391 | options: GestureOptionsRequired, |
| 392 | instance: ViewTransitionInstance, |
| 393 | types: Array<string>, |
| 394 | ) => void | (() => void), |
| 395 | }; |
| 396 | |
| 397 | export type ActivityProps = { |
| 398 | mode?: 'hidden' | 'visible' | null | void, |
| 399 | children?: ReactNodeList, |
| 400 | name?: string, |
| 401 | }; |
| 402 | |
| 403 | export type SuspenseProps = { |
| 404 | children?: ReactNodeList, |
| 405 | fallback?: ReactNodeList, |
| 406 | |
| 407 | // TODO: Add "unstable_" prefix? |
| 408 | suspenseCallback?: (Set<Wakeable> | null) => mixed, |
| 409 | |
| 410 | unstable_avoidThisFallback?: boolean, |
| 411 | defer?: boolean, |
| 412 | name?: string, |
| 413 | }; |
| 414 | |
| 415 | export type SuspenseListRevealOrder = |
| 416 | | 'forwards' |
| 417 | | 'backwards' |
| 418 | | 'unstable_legacy-backwards' |
| 419 | | 'together' |
| 420 | | 'independent' |
| 421 | | void; |
| 422 | |
| 423 | export type SuspenseListTailMode = 'visible' | 'collapsed' | 'hidden' | void; |
| 424 | |
| 425 | // A SuspenseList row cannot include a nested Array since it's an easy mistake to not realize it |
| 426 | // is treated as a single row. A Fragment can be used to intentionally have multiple children as |
| 427 | // a single row. |
| 428 | type SuspenseListRow = Exclude< |
| 429 | ReactNodeList, |
| 430 | Iterable<React$Node> | AsyncIterable<React$Node>, |
| 431 | >; |
| 432 | |
| 433 | type DirectionalSuspenseListProps = { |
| 434 | // Directional SuspenseList are defined by an array of children or multiple slots to JSX |
| 435 | // It does not allow a single element child. |
| 436 | children?: Iterable<SuspenseListRow> | AsyncIterable<SuspenseListRow>, // Note: AsyncIterable is experimental. |
| 437 | revealOrder: 'forwards' | 'backwards' | 'unstable_legacy-backwards', |
| 438 | tail?: SuspenseListTailMode, |
| 439 | }; |
| 440 | |
| 441 | type NonDirectionalSuspenseListProps = { |
| 442 | children?: ReactNodeList, |
| 443 | revealOrder?: 'independent' | 'together' | void, |
| 444 | tail?: void, |
| 445 | }; |
| 446 | |
| 447 | export type SuspenseListProps = |
| 448 | | DirectionalSuspenseListProps |
| 449 | | NonDirectionalSuspenseListProps; |
| 450 | |
| 451 | export type TracingMarkerProps = { |
| 452 | name: string, |
| 453 | children?: ReactNodeList, |
| 454 | }; |
| 455 | |
| 456 | export type CacheProps = { |
| 457 | children?: ReactNodeList, |
| 458 | }; |
| 459 | |
| 460 | export type ProfilerPhase = 'mount' | 'update' | 'nested-update'; |
| 461 | |
| 462 | export type ProfilerProps = { |
| 463 | id?: string, |
| 464 | onRender?: ( |
| 465 | id: void | string, |
| 466 | phase: ProfilerPhase, |
| 467 | actualDuration: number, |
| 468 | baseDuration: number, |
| 469 | startTime: number, |
| 470 | commitTime: number, |
| 471 | ) => void, |
| 472 | onCommit?: ( |
| 473 | id: void | string, |
| 474 | phase: ProfilerPhase, |
| 475 | effectDuration: number, |
| 476 | commitTime: number, |
| 477 | ) => void, |
| 478 | children?: ReactNodeList, |
| 479 | }; |