diff --git a/packages/react-dom/src/server/ReactPartialRenderer.js b/packages/react-dom/src/server/ReactPartialRenderer.js index e06f1df9bcd88..a28b41fc12c90 100644 --- a/packages/react-dom/src/server/ReactPartialRenderer.js +++ b/packages/react-dom/src/server/ReactPartialRenderer.js @@ -9,7 +9,7 @@ import type {ThreadID} from './ReactThreadIDAllocator'; import type {ReactElement} from 'shared/ReactElementType'; -import type {LazyComponent} from 'shared/ReactLazyComponent'; +import type {LazyComponent} from 'react/src/ReactLazy'; import type {ReactProvider, ReactContext} from 'shared/ReactTypes'; import * as React from 'react'; @@ -17,12 +17,8 @@ import invariant from 'shared/invariant'; import getComponentName from 'shared/getComponentName'; import describeComponentFrame from 'shared/describeComponentFrame'; import ReactSharedInternals from 'shared/ReactSharedInternals'; -import { - Resolved, - Rejected, - Pending, - initializeLazyComponentType, -} from 'shared/ReactLazyComponent'; +import {initializeLazyComponentType} from 'shared/ReactLazyComponent'; +import {Resolved, Rejected, Pending} from 'shared/ReactLazyStatusTags'; import { warnAboutDeprecatedLifecycles, disableLegacyContext, diff --git a/packages/react-reconciler/src/ReactFiberLazyComponent.js b/packages/react-reconciler/src/ReactFiberLazyComponent.js index 290458eb96928..394b35ae906d8 100644 --- a/packages/react-reconciler/src/ReactFiberLazyComponent.js +++ b/packages/react-reconciler/src/ReactFiberLazyComponent.js @@ -7,9 +7,10 @@ * @flow */ -import type {LazyComponent} from 'shared/ReactLazyComponent'; +import type {LazyComponent} from 'react/src/ReactLazy'; -import {Resolved, initializeLazyComponentType} from 'shared/ReactLazyComponent'; +import {Resolved} from 'shared/ReactLazyStatusTags'; +import {initializeLazyComponentType} from 'shared/ReactLazyComponent'; export function resolveDefaultProps(Component: any, baseProps: Object): Object { if (Component && Component.defaultProps) { diff --git a/packages/react/src/ReactLazy.js b/packages/react/src/ReactLazy.js index c804c53741a60..1de3189c923c6 100644 --- a/packages/react/src/ReactLazy.js +++ b/packages/react/src/ReactLazy.js @@ -3,25 +3,61 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. + * + * @flow */ -import type {LazyComponent, Thenable} from 'shared/ReactLazyComponent'; - import {REACT_LAZY_TYPE} from 'shared/ReactSymbols'; -export function lazy(ctor: () => Thenable): LazyComponent { - let lazyType = { +type Thenable = { + then(resolve: (T) => mixed, reject: (mixed) => mixed): R, +}; + +export type UninitializedLazyComponent = { + $$typeof: Symbol | number, + _status: -1, + _result: () => Thenable<{default: T, ...} | T, mixed>, +}; + +export type PendingLazyComponent = { + $$typeof: Symbol | number, + _status: 0, + _result: Thenable<{default: T, ...} | T, mixed>, +}; + +export type ResolvedLazyComponent = { + $$typeof: Symbol | number, + _status: 1, + _result: T, +}; + +export type RejectedLazyComponent = { + $$typeof: Symbol | number, + _status: 2, + _result: mixed, +}; + +export type LazyComponent = + | UninitializedLazyComponent + | PendingLazyComponent + | ResolvedLazyComponent + | RejectedLazyComponent; + +export function lazy( + ctor: () => Thenable<{default: T, ...} | T, mixed>, +): LazyComponent { + let lazyType: LazyComponent = { $$typeof: REACT_LAZY_TYPE, - _ctor: ctor, // React uses these fields to store the result. _status: -1, - _result: null, + _result: ctor, }; if (__DEV__) { // In production, this would just set it on the object. let defaultProps; let propTypes; + // $FlowFixMe Object.defineProperties(lazyType, { defaultProps: { configurable: true, @@ -36,6 +72,7 @@ export function lazy(ctor: () => Thenable): LazyComponent { ); defaultProps = newDefaultProps; // Match production behavior more closely: + // $FlowFixMe Object.defineProperty(lazyType, 'defaultProps', { enumerable: true, }); @@ -54,6 +91,7 @@ export function lazy(ctor: () => Thenable): LazyComponent { ); propTypes = newPropTypes; // Match production behavior more closely: + // $FlowFixMe Object.defineProperty(lazyType, 'propTypes', { enumerable: true, }); diff --git a/packages/shared/ReactLazyComponent.js b/packages/shared/ReactLazyComponent.js index 246ba41e83da5..24b360a1e57a1 100644 --- a/packages/shared/ReactLazyComponent.js +++ b/packages/shared/ReactLazyComponent.js @@ -7,35 +7,23 @@ * @flow */ -export type Thenable = { - then(resolve: (T) => mixed, reject: (mixed) => mixed): R, - ... -}; +import type { + PendingLazyComponent, + ResolvedLazyComponent, + RejectedLazyComponent, + LazyComponent, +} from 'react/src/ReactLazy'; -export type LazyComponent = { - $$typeof: Symbol | number, - _ctor: () => Thenable<{default: T, ...}, mixed>, - _status: 0 | 1 | 2, - _result: any, - ... -}; - -type ResolvedLazyComponent = { - $$typeof: Symbol | number, - _ctor: () => Thenable<{default: T, ...}, mixed>, - _status: 1, - _result: any, - ... -}; - -export const Uninitialized = -1; -export const Pending = 0; -export const Resolved = 1; -export const Rejected = 2; +import { + Uninitialized, + Pending, + Resolved, + Rejected, +} from './ReactLazyStatusTags'; export function refineResolvedLazyComponent( lazyComponent: LazyComponent, -): ResolvedLazyComponent | null { +): T | null { return lazyComponent._status === Resolved ? lazyComponent._result : null; } @@ -43,10 +31,16 @@ export function initializeLazyComponentType( lazyComponent: LazyComponent, ): void { if (lazyComponent._status === Uninitialized) { - lazyComponent._status = Pending; - const ctor = lazyComponent._ctor; + let ctor = lazyComponent._result; + if (!ctor) { + // TODO: Remove this later. THis only exists in case you use an older "react" package. + ctor = ((lazyComponent: any)._ctor: typeof ctor); + } const thenable = ctor(); - lazyComponent._result = thenable; + // Transition to the next state. + const pending: PendingLazyComponent = (lazyComponent: any); + pending._status = Pending; + pending._result = thenable; thenable.then( moduleObject => { if (lazyComponent._status === Pending) { @@ -61,14 +55,18 @@ export function initializeLazyComponentType( ); } } - lazyComponent._status = Resolved; - lazyComponent._result = defaultExport; + // Transition to the next state. + const resolved: ResolvedLazyComponent = (lazyComponent: any); + resolved._status = Resolved; + resolved._result = defaultExport; } }, error => { if (lazyComponent._status === Pending) { - lazyComponent._status = Rejected; - lazyComponent._result = error; + // Transition to the next state. + const rejected: RejectedLazyComponent = (lazyComponent: any); + rejected._status = Rejected; + rejected._result = error; } }, ); diff --git a/packages/shared/ReactLazyStatusTags.js b/packages/shared/ReactLazyStatusTags.js new file mode 100644 index 0000000000000..8baa0ad217248 --- /dev/null +++ b/packages/shared/ReactLazyStatusTags.js @@ -0,0 +1,14 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + +// TODO: Move this to "react" once we can import from externals. +export const Uninitialized = -1; +export const Pending = 0; +export const Resolved = 1; +export const Rejected = 2; diff --git a/packages/shared/getComponentName.js b/packages/shared/getComponentName.js index 9694732ce5d96..9817ea21963ee 100644 --- a/packages/shared/getComponentName.js +++ b/packages/shared/getComponentName.js @@ -7,7 +7,7 @@ * @flow */ -import type {LazyComponent} from 'shared/ReactLazyComponent'; +import type {LazyComponent} from 'react/src/ReactLazy'; import { REACT_CONTEXT_TYPE,