diff --git a/.flowconfig b/.flowconfig index 5562ed1a069..a294f39e675 100644 --- a/.flowconfig +++ b/.flowconfig @@ -2,7 +2,15 @@ /fixtures/.* /build/.* -/scripts/.* +/scripts/bench/.* + +# These shims are copied into external projects: +/scripts/rollup/shims/facebook-www/.* +/scripts/rollup/shims/react-native/.* + +# Note: intentionally *don't* ignore /scripts/rollup/shims/rollup/ +# because it is part of the build and isn't external. + /.*/node_modules/y18n/.* /node_modules/chrome-devtools-frontend/.* /node_modules/devtools-timeline-model/.* diff --git a/packages/react-cs-renderer/src/ReactNativeCSFeatureFlags.js b/packages/react-cs-renderer/src/ReactNativeCSFeatureFlags.js index 2e768861949..7922bd373d4 100644 --- a/packages/react-cs-renderer/src/ReactNativeCSFeatureFlags.js +++ b/packages/react-cs-renderer/src/ReactNativeCSFeatureFlags.js @@ -7,17 +7,21 @@ * @flow */ -import type {FeatureFlags} from 'shared/ReactFeatureFlags'; +import typeof * as FeatureFlagsType from 'shared/ReactFeatureFlags'; +import typeof * as CSFeatureFlagsType from './ReactNativeCSFeatureFlags'; -var ReactNativeCSFeatureFlags: FeatureFlags = { - enableAsyncSubtreeAPI: true, - enableAsyncSchedulingByDefaultInReactDOM: false, - enableReactFragment: false, - enableCreateRoot: false, - // React Native CS uses persistent reconciler. - enableMutatingReconciler: false, - enableNoopReconciler: false, - enablePersistentReconciler: true, -}; +export const enableAsyncSubtreeAPI = true; +export const enableAsyncSchedulingByDefaultInReactDOM = false; +export const enableReactFragment = false; +export const enableCreateRoot = false; -export default ReactNativeCSFeatureFlags; +// React Native CS uses persistent reconciler. +export const enableMutatingReconciler = false; +export const enableNoopReconciler = false; +export const enablePersistentReconciler = true; + +// Flow magic to verify the exports of this file match the original version. +// eslint-disable-next-line no-unused-vars +type Check<_X, Y: _X, X: Y=_X> = null; +// eslint-disable-next-line no-unused-expressions +(null: Check); diff --git a/packages/react-dom/src/client/ReactDOM.js b/packages/react-dom/src/client/ReactDOM.js index d89497a079c..0c699042644 100644 --- a/packages/react-dom/src/client/ReactDOM.js +++ b/packages/react-dom/src/client/ReactDOM.js @@ -25,7 +25,10 @@ import * as EventPluginHub from 'events/EventPluginHub'; import * as EventPluginRegistry from 'events/EventPluginRegistry'; import * as EventPropagators from 'events/EventPropagators'; import * as ReactInstanceMap from 'shared/ReactInstanceMap'; -import ReactFeatureFlags from 'shared/ReactFeatureFlags'; +import { + enableAsyncSchedulingByDefaultInReactDOM, + enableCreateRoot, +} from 'shared/ReactFeatureFlags'; import ReactVersion from 'shared/ReactVersion'; import * as ReactDOMFrameScheduling from 'shared/ReactDOMFrameScheduling'; import {ReactCurrentOwner} from 'shared/ReactGlobalSharedState'; @@ -633,7 +636,7 @@ var DOMRenderer = ReactFiberReconciler({ scheduleDeferredCallback: ReactDOMFrameScheduling.rIC, - useSyncScheduling: !ReactFeatureFlags.enableAsyncSchedulingByDefaultInReactDOM, + useSyncScheduling: !enableAsyncSchedulingByDefaultInReactDOM, }); ReactGenericBatching.injection.injectFiberBatchedUpdates( @@ -945,7 +948,7 @@ var ReactDOM: Object = { }, }; -if (ReactFeatureFlags.enableCreateRoot) { +if (enableCreateRoot) { ReactDOM.createRoot = function createRoot( container: DOMContainer, options?: RootOptions, diff --git a/packages/react-noop-renderer/src/ReactNoop.js b/packages/react-noop-renderer/src/ReactNoop.js index 66ffccf1212..ae4b1f5c853 100644 --- a/packages/react-noop-renderer/src/ReactNoop.js +++ b/packages/react-noop-renderer/src/ReactNoop.js @@ -21,7 +21,7 @@ import type {UpdateQueue} from 'react-reconciler/src/ReactFiberUpdateQueue'; import ReactFiberInstrumentation from 'react-reconciler/src/ReactFiberInstrumentation'; import ReactFiberReconciler from 'react-reconciler'; -import ReactFeatureFlags from 'shared/ReactFeatureFlags'; +import {enablePersistentReconciler} from 'shared/ReactFeatureFlags'; import * as ReactInstanceMap from 'shared/ReactInstanceMap'; import emptyObject from 'fbjs/lib/emptyObject'; import expect from 'expect'; @@ -213,7 +213,7 @@ var NoopRenderer = ReactFiberReconciler({ }, }); -var PersistentNoopRenderer = ReactFeatureFlags.enablePersistentReconciler +var PersistentNoopRenderer = enablePersistentReconciler ? ReactFiberReconciler({ ...SharedHostConfig, persistence: { diff --git a/packages/react-reconciler/src/ReactChildFiber.js b/packages/react-reconciler/src/ReactChildFiber.js index 1c2b072da3b..b2e91e4e1cf 100644 --- a/packages/react-reconciler/src/ReactChildFiber.js +++ b/packages/react-reconciler/src/ReactChildFiber.js @@ -14,7 +14,7 @@ import type { ExpirationTime, } from 'react-reconciler/src/ReactFiberExpirationTime'; -import ReactFeatureFlags from 'shared/ReactFeatureFlags'; +import {enableReactFragment} from 'shared/ReactFeatureFlags'; import {NoEffect, Placement, Deletion} from 'shared/ReactTypeOfSideEffect'; import { FunctionalComponent, @@ -1426,7 +1426,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) { // This leads to an ambiguity between <>{[...]} and <>.... // We treat the ambiguous cases above the same. if ( - ReactFeatureFlags.enableReactFragment && + enableReactFragment && typeof newChild === 'object' && newChild !== null && newChild.type === REACT_FRAGMENT_TYPE && diff --git a/packages/react-reconciler/src/ReactFiberClassComponent.js b/packages/react-reconciler/src/ReactFiberClassComponent.js index 295aa362dcf..39e3993a1c0 100644 --- a/packages/react-reconciler/src/ReactFiberClassComponent.js +++ b/packages/react-reconciler/src/ReactFiberClassComponent.js @@ -11,7 +11,7 @@ import type {Fiber} from './ReactFiber'; import type {ExpirationTime} from './ReactFiberExpirationTime'; import {Update} from 'shared/ReactTypeOfSideEffect'; -import ReactFeatureFlags from 'shared/ReactFeatureFlags'; +import {enableAsyncSubtreeAPI} from 'shared/ReactFeatureFlags'; import {isMounted} from 'shared/ReactFiberTreeReflection'; import * as ReactInstanceMap from 'shared/ReactInstanceMap'; import emptyObject from 'fbjs/lib/emptyObject'; @@ -450,7 +450,7 @@ export default function( instance.context = getMaskedContext(workInProgress, unmaskedContext); if ( - ReactFeatureFlags.enableAsyncSubtreeAPI && + enableAsyncSubtreeAPI && workInProgress.type != null && workInProgress.type.prototype != null && workInProgress.type.prototype.unstable_isAsyncReactComponent === true diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.js b/packages/react-reconciler/src/ReactFiberCommitWork.js index 338b5935deb..86be8e591de 100644 --- a/packages/react-reconciler/src/ReactFiberCommitWork.js +++ b/packages/react-reconciler/src/ReactFiberCommitWork.js @@ -10,7 +10,11 @@ import type {HostConfig} from 'react-reconciler'; import type {Fiber} from './ReactFiber'; -import ReactFeatureFlags from 'shared/ReactFeatureFlags'; +import { + enableMutatingReconciler, + enableNoopReconciler, + enablePersistentReconciler, +} from 'shared/ReactFeatureFlags'; import { ClassComponent, HostRoot, @@ -218,12 +222,9 @@ export default function( // TODO: this is recursive. // We are also not using this parent because // the portal will get pushed immediately. - if (ReactFeatureFlags.enableMutatingReconciler && mutation) { + if (enableMutatingReconciler && mutation) { unmountHostComponents(current); - } else if ( - ReactFeatureFlags.enablePersistentReconciler && - persistence - ) { + } else if (enablePersistentReconciler && persistence) { emptyPortalContainer(current); } return; @@ -324,10 +325,7 @@ export default function( // Noop }; } - if ( - ReactFeatureFlags.enablePersistentReconciler || - ReactFeatureFlags.enableNoopReconciler - ) { + if (enablePersistentReconciler || enableNoopReconciler) { return { commitResetTextContent(finishedWork: Fiber) {}, commitPlacement(finishedWork: Fiber) {}, @@ -660,7 +658,7 @@ export default function( resetTextContent(current.stateNode); } - if (ReactFeatureFlags.enableMutatingReconciler) { + if (enableMutatingReconciler) { return { commitResetTextContent, commitPlacement, diff --git a/packages/react-reconciler/src/ReactFiberCompleteWork.js b/packages/react-reconciler/src/ReactFiberCompleteWork.js index f28ddcf312d..e0c2e6b7a05 100644 --- a/packages/react-reconciler/src/ReactFiberCompleteWork.js +++ b/packages/react-reconciler/src/ReactFiberCompleteWork.js @@ -15,7 +15,11 @@ import type {HostContext} from './ReactFiberHostContext'; import type {HydrationContext} from './ReactFiberHydrationContext'; import type {FiberRoot} from './ReactFiberRoot'; -import ReactFeatureFlags from 'shared/ReactFeatureFlags'; +import { + enableMutatingReconciler, + enablePersistentReconciler, + enableNoopReconciler, +} from 'shared/ReactFeatureFlags'; import { IndeterminateComponent, FunctionalComponent, @@ -180,7 +184,7 @@ export default function( let updateHostComponent; let updateHostText; if (mutation) { - if (ReactFeatureFlags.enableMutatingReconciler) { + if (enableMutatingReconciler) { // Mutation mode updateHostContainer = function(workInProgress: Fiber) { // Noop @@ -217,7 +221,7 @@ export default function( invariant(false, 'Mutating reconciler is disabled.'); } } else if (persistence) { - if (ReactFeatureFlags.enablePersistentReconciler) { + if (enablePersistentReconciler) { // Persistent host tree mode const { cloneInstance, @@ -354,7 +358,7 @@ export default function( invariant(false, 'Persistent reconciler is disabled.'); } } else { - if (ReactFeatureFlags.enableNoopReconciler) { + if (enableNoopReconciler) { // No host operations updateHostContainer = function(workInProgress: Fiber) { // Noop diff --git a/packages/react-reconciler/src/ReactFiberReconciler.js b/packages/react-reconciler/src/ReactFiberReconciler.js index 42f60bb5f5a..a7e85f81f6b 100644 --- a/packages/react-reconciler/src/ReactFiberReconciler.js +++ b/packages/react-reconciler/src/ReactFiberReconciler.js @@ -11,7 +11,7 @@ import type {Fiber} from './ReactFiber'; import type {FiberRoot} from './ReactFiberRoot'; import type {ReactNodeList} from 'shared/ReactTypes'; -import ReactFeatureFlags from 'shared/ReactFeatureFlags'; +import {enableAsyncSubtreeAPI} from 'shared/ReactFeatureFlags'; import { findCurrentHostFiber, findCurrentHostFiberWithNoPortals, @@ -303,7 +303,7 @@ export default function( // treat updates to the root as async. This is a bit weird but lets us // avoid a separate `renderAsync` API. if ( - ReactFeatureFlags.enableAsyncSubtreeAPI && + enableAsyncSubtreeAPI && element != null && element.type != null && element.type.prototype != null && diff --git a/packages/react/src/React.js b/packages/react/src/React.js index a0622193bbf..f25181ea803 100644 --- a/packages/react/src/React.js +++ b/packages/react/src/React.js @@ -7,7 +7,7 @@ import assign from 'object-assign'; import ReactVersion from 'shared/ReactVersion'; -import ReactFeatureFlags from 'shared/ReactFeatureFlags'; +import {enableReactFragment} from 'shared/ReactFeatureFlags'; import {Component, PureComponent, AsyncComponent} from './ReactBaseClasses'; import {forEach, map, count, toArray, only} from './ReactChildren'; @@ -58,7 +58,7 @@ var React = { }, }; -if (ReactFeatureFlags.enableReactFragment) { +if (enableReactFragment) { React.Fragment = REACT_FRAGMENT_TYPE; } diff --git a/packages/shared/ReactFeatureFlags.js b/packages/shared/ReactFeatureFlags.js index b9f2d2a952e..12c109e30f9 100644 --- a/packages/shared/ReactFeatureFlags.js +++ b/packages/shared/ReactFeatureFlags.js @@ -7,35 +7,16 @@ * @flow */ -export type FeatureFlags = {| - enableAsyncSubtreeAPI: boolean, - enableAsyncSchedulingByDefaultInReactDOM: boolean, - enableMutatingReconciler: boolean, - enableNoopReconciler: boolean, - enablePersistentReconciler: boolean, - enableReactFragment: boolean, - enableCreateRoot: boolean, -|}; +export const enableAsyncSubtreeAPI = true; +export const enableAsyncSchedulingByDefaultInReactDOM = false; +// Exports React.Fragment +export const enableReactFragment = false; +// Exports ReactDOM.createRoot +export const enableCreateRoot = false; -var ReactFeatureFlags: FeatureFlags = { - enableAsyncSubtreeAPI: true, - enableAsyncSchedulingByDefaultInReactDOM: false, - // Mutating mode (React DOM, React ART, React Native): - enableMutatingReconciler: true, - // Experimental noop mode (currently unused): - enableNoopReconciler: false, - // Experimental persistent mode (CS): - enablePersistentReconciler: false, - // Exports React.Fragment - enableReactFragment: false, - // Exports ReactDOM.createRoot - enableCreateRoot: false, -}; - -if (__DEV__) { - if (Object.freeze) { - Object.freeze(ReactFeatureFlags); - } -} - -export default ReactFeatureFlags; +// Mutating mode (React DOM, React ART, React Native): +export const enableMutatingReconciler = true; +// Experimental noop mode (currently unused): +export const enableNoopReconciler = false; +// Experimental persistent mode (CS): +export const enablePersistentReconciler = false; diff --git a/scripts/flow/environment.js b/scripts/flow/environment.js index 4bdb13d069c..f06d9e2929e 100644 --- a/scripts/flow/environment.js +++ b/scripts/flow/environment.js @@ -12,3 +12,8 @@ declare var __REACT_DEVTOOLS_GLOBAL_HOOK__: any; /*?{ inject: ?((stuff: Object) => void) };*/ + +// ReactFeatureFlags rollup shim for www imports the www implementation. +declare module 'ReactFeatureFlags' { + declare module.exports: any; +} diff --git a/scripts/jest/setup.js b/scripts/jest/setup.js index 007e9f36d22..63bdc9fbbf6 100644 --- a/scripts/jest/setup.js +++ b/scripts/jest/setup.js @@ -1,12 +1,9 @@ 'use strict'; -// We want to globally mock this but jest doesn't let us do that by default -// for a file that already exists. So we have to explicitly mock it. jest.mock('shared/ReactFeatureFlags', () => { - const flags = require.requireActual('shared/ReactFeatureFlags').default; - return Object.assign({}, flags, { - disableNewFiberFeatures: true, - }); + // We can alter flags based on environment here + // (e.g. for CI runs with different flags). + return require.requireActual('shared/ReactFeatureFlags'); }); // Error logging varies between Fiber and Stack; diff --git a/scripts/rollup/results.json b/scripts/rollup/results.json index 5b4fa94cc99..a465f01be66 100644 --- a/scripts/rollup/results.json +++ b/scripts/rollup/results.json @@ -1,52 +1,52 @@ { "bundleSizes": { "react.development.js (UMD_DEV)": { - "size": 57960, - "gzip": 15055 + "size": 57612, + "gzip": 14938 }, "react.production.min.js (UMD_PROD)": { "size": 6672, "gzip": 2772 }, "react.development.js (NODE_DEV)": { - "size": 48341, - "gzip": 12749 + "size": 47993, + "gzip": 12640 }, "react.production.min.js (NODE_PROD)": { "size": 5471, "gzip": 2349 }, "React-dev.js (FB_DEV)": { - "size": 45254, - "gzip": 11809 + "size": 45761, + "gzip": 11884 }, "React-prod.js (FB_PROD)": { - "size": 25804, - "gzip": 6870 + "size": 26012, + "gzip": 6885 }, "react-dom.development.js (UMD_DEV)": { - "size": 589183, - "gzip": 133823 + "size": 589114, + "gzip": 133729 }, "react-dom.production.min.js (UMD_PROD)": { - "size": 96544, - "gzip": 31188 + "size": 94334, + "gzip": 30564 }, "react-dom.development.js (NODE_DEV)": { - "size": 570160, - "gzip": 129121 + "size": 569900, + "gzip": 129020 }, "react-dom.production.min.js (NODE_PROD)": { - "size": 94731, - "gzip": 30346 + "size": 92521, + "gzip": 29735 }, "ReactDOM-dev.js (FB_DEV)": { - "size": 571472, - "gzip": 129612 + "size": 572245, + "gzip": 129735 }, "ReactDOM-prod.js (FB_PROD)": { - "size": 405312, - "gzip": 90089 + "size": 405997, + "gzip": 90194 }, "react-dom-test-utils.development.js (NODE_DEV)": { "size": 37876, @@ -61,8 +61,8 @@ "gzip": 10182 }, "react-dom-unstable-native-dependencies.development.js (UMD_DEV)": { - "size": 66641, - "gzip": 16671 + "size": 66832, + "gzip": 16686 }, "react-dom-unstable-native-dependencies.production.min.js (UMD_PROD)": { "size": 11349, @@ -85,8 +85,8 @@ "gzip": 12586 }, "react-dom-server.browser.development.js (UMD_DEV)": { - "size": 100894, - "gzip": 26193 + "size": 101085, + "gzip": 26194 }, "react-dom-server.browser.production.min.js (UMD_PROD)": { "size": 14713, @@ -117,64 +117,64 @@ "gzip": 6016 }, "react-art.development.js (UMD_DEV)": { - "size": 361363, - "gzip": 78801 + "size": 361168, + "gzip": 78675 }, "react-art.production.min.js (UMD_PROD)": { - "size": 84853, - "gzip": 26004 + "size": 82786, + "gzip": 25335 }, "react-art.development.js (NODE_DEV)": { - "size": 285762, - "gzip": 59878 + "size": 285376, + "gzip": 59744 }, "react-art.production.min.js (NODE_PROD)": { - "size": 48726, - "gzip": 15050 + "size": 46664, + "gzip": 14576 }, "ReactART-dev.js (FB_DEV)": { - "size": 284015, - "gzip": 59653 + "size": 284412, + "gzip": 59714 }, "ReactART-prod.js (FB_PROD)": { - "size": 209267, - "gzip": 43024 + "size": 209350, + "gzip": 43045 }, "ReactNativeRenderer-dev.js (RN_DEV)": { - "size": 264248, - "gzip": 45270 + "size": 263840, + "gzip": 45183 }, "ReactNativeRenderer-prod.js (RN_PROD)": { - "size": 202770, - "gzip": 34504 + "size": 202457, + "gzip": 34443 }, "ReactRTRenderer-dev.js (RN_DEV)": { - "size": 195970, - "gzip": 32882 + "size": 195570, + "gzip": 32792 }, "ReactRTRenderer-prod.js (RN_PROD)": { - "size": 143566, - "gzip": 23595 + "size": 143253, + "gzip": 23524 }, "ReactCSRenderer-dev.js (RN_DEV)": { - "size": 189548, - "gzip": 31563 + "size": 189107, + "gzip": 31467 }, "ReactCSRenderer-prod.js (RN_PROD)": { - "size": 139382, - "gzip": 22608 + "size": 138973, + "gzip": 22523 }, "react-test-renderer.development.js (NODE_DEV)": { - "size": 284199, - "gzip": 58944 + "size": 283813, + "gzip": 58810 }, "react-test-renderer.production.min.js (NODE_PROD)": { - "size": 47325, - "gzip": 14489 + "size": 45266, + "gzip": 13979 }, "ReactTestRenderer-dev.js (FB_DEV)": { - "size": 282462, - "gzip": 58722 + "size": 282859, + "gzip": 58787 }, "react-test-renderer-shallow.development.js (NODE_DEV)": { "size": 10657, @@ -189,16 +189,16 @@ "gzip": 2515 }, "react-noop-renderer.development.js (NODE_DEV)": { - "size": 280181, - "gzip": 57920 + "size": 279777, + "gzip": 57797 }, "react-reconciler.development.js (NODE_DEV)": { - "size": 264938, - "gzip": 54474 + "size": 264552, + "gzip": 54331 }, "react-reconciler.production.min.js (NODE_PROD)": { - "size": 40581, - "gzip": 12611 + "size": 38523, + "gzip": 12008 }, "react-call-return.development.js (NODE_DEV)": { "size": 3048, diff --git a/scripts/rollup/shims/rollup/ReactCurrentOwner-www.js b/scripts/rollup/shims/rollup/ReactCurrentOwner-www.js index b59c607610f..b10bcd8e09c 100644 --- a/scripts/rollup/shims/rollup/ReactCurrentOwner-www.js +++ b/scripts/rollup/shims/rollup/ReactCurrentOwner-www.js @@ -1 +1,8 @@ +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + export default require('ReactCurrentOwner'); diff --git a/scripts/rollup/shims/rollup/ReactFeatureFlags-www.js b/scripts/rollup/shims/rollup/ReactFeatureFlags-www.js index fbb9c83d68e..9958c526734 100644 --- a/scripts/rollup/shims/rollup/ReactFeatureFlags-www.js +++ b/scripts/rollup/shims/rollup/ReactFeatureFlags-www.js @@ -1 +1,28 @@ -export default require('ReactFeatureFlags'); +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + +import typeof * as FeatureFlagsType from 'shared/ReactFeatureFlags'; +import typeof * as FeatureFlagsShimType from './ReactFeatureFlags-www'; + +// Re-export all flags from the www version. +export const { + enableAsyncSubtreeAPI, + enableAsyncSchedulingByDefaultInReactDOM, + enableReactFragment, + enableCreateRoot, + enableMutatingReconciler, + enableNoopReconciler, + enablePersistentReconciler, +} = require('ReactFeatureFlags'); + +// Flow magic to verify the exports of this file match the original version. +// eslint-disable-next-line no-unused-vars +type Check<_X, Y: _X, X: Y=_X> = null; +// eslint-disable-next-line no-unused-expressions +(null: Check); diff --git a/scripts/rollup/shims/rollup/assign-umd.js b/scripts/rollup/shims/rollup/assign-umd.js index ea1230646b5..c800db1ea85 100644 --- a/scripts/rollup/shims/rollup/assign-umd.js +++ b/scripts/rollup/shims/rollup/assign-umd.js @@ -1,3 +1,12 @@ +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + import React from 'react'; const ReactInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; diff --git a/scripts/rollup/shims/rollup/lowPriorityWarning-www.js b/scripts/rollup/shims/rollup/lowPriorityWarning-www.js index b2bc5b3f52e..dabd7be625d 100644 --- a/scripts/rollup/shims/rollup/lowPriorityWarning-www.js +++ b/scripts/rollup/shims/rollup/lowPriorityWarning-www.js @@ -1 +1,8 @@ +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + export default require('lowPriorityWarning');