From ed3d4c97eff7290a02520ceb45fe07c51beb5b7a Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Fri, 21 Feb 2020 15:18:19 -0800 Subject: [PATCH 01/12] Add options for forked entry points We currently fork .fb.js entry points. This adds a few more options. .modern.fb.js - experimental FB builds .classic.fb.js - stable FB builds .fb.js - if no other FB build, use this for FB builds .experimental.js - experimental builds .stable.js - stable builds .js - used if no other override exists This will be used to have different ES exports for different builds. --- scripts/rollup/build.js | 46 ++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/scripts/rollup/build.js b/scripts/rollup/build.js index b1e4ff887e3..020a28349ce 100644 --- a/scripts/rollup/build.js +++ b/scripts/rollup/build.js @@ -479,6 +479,40 @@ function shouldSkipBundle(bundle, bundleType) { return false; } +function resolveEntryFork(resolvedEntry, isFBBundle) { + // Pick which entry point fork to use: + // .modern.fb.js + // .classic.fb.js + // .fb.js + // .stable.js + // .experimental.js + // .js + + if (isFBBundle) { + const resolvedFBEntry = resolvedEntry.replace( + '.js', + __EXPERIMENTAL__ ? '.modern.fb.js' : '.classic.fb.js' + ); + if (fs.existsSync(resolvedFBEntry)) { + return resolvedFBEntry; + } + const resolvedGenericFBEntry = resolvedEntry.replace('.js', '.fb.js'); + if (fs.existsSync(resolvedGenericFBEntry)) { + return resolvedGenericFBEntry; + } + // Even if it's a FB bundle we fallthrough to pick stable or experimental if we don't have an FB fork. + } + const resolvedForkedEntry = resolvedEntry.replace( + '.js', + __EXPERIMENTAL__ ? '.experimental.js' : '.stable.js' + ); + if (fs.existsSync(resolvedForkedEntry)) { + return resolvedForkedEntry; + } + // Just use the plain .js one. + return resolvedEntry; +} + async function createBundle(bundle, bundleType) { if (shouldSkipBundle(bundle, bundleType)) { return; @@ -490,17 +524,15 @@ async function createBundle(bundle, bundleType) { const format = getFormat(bundleType); const packageName = Packaging.getPackageName(bundle.entry); - let resolvedEntry = require.resolve(bundle.entry); const isFBBundle = bundleType === FB_WWW_DEV || bundleType === FB_WWW_PROD || bundleType === FB_WWW_PROFILING; - if (isFBBundle) { - const resolvedFBEntry = resolvedEntry.replace('.js', '.fb.js'); - if (fs.existsSync(resolvedFBEntry)) { - resolvedEntry = resolvedFBEntry; - } - } + + let resolvedEntry = resolveEntryFork( + require.resolve(bundle.entry), + isFBBundle + ); const shouldBundleDependencies = bundleType === UMD_DEV || From 1355fc176249e84307fdaea09fa6ad83757de51d Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Fri, 21 Feb 2020 19:00:48 -0800 Subject: [PATCH 02/12] Switch React to named exports --- packages/react/index.js | 4 +- packages/react/src/React.js | 139 ++++++++++++++---------------------- 2 files changed, 56 insertions(+), 87 deletions(-) diff --git a/packages/react/index.js b/packages/react/index.js index 4268898c088..3e2a28ef2bb 100644 --- a/packages/react/index.js +++ b/packages/react/index.js @@ -11,6 +11,4 @@ const React = require('./src/React'); -// TODO: decide on the top-level export form. -// This is hacky but makes it work with both Rollup and Jest. -module.exports = React.default || React; +module.exports = React; diff --git a/packages/react/src/React.js b/packages/react/src/React.js index 23fb0f87917..3fd7304f993 100644 --- a/packages/react/src/React.js +++ b/packages/react/src/React.js @@ -18,11 +18,11 @@ import {Component, PureComponent} from './ReactBaseClasses'; import {createRef} from './ReactCreateRef'; import {forEach, map, count, toArray, only} from './ReactChildren'; import { - createElement, - createFactory, - cloneElement, + createElement as createElementProd, + createFactory as createFactoryProd, + cloneElement as cloneElementProd, isValidElement, - jsx, + jsx as jsxProd, } from './ReactElement'; import {createContext} from './ReactContext'; import {lazy} from './ReactLazy'; @@ -57,33 +57,35 @@ import ReactSharedInternals from './ReactSharedInternals'; import createFundamental from 'shared/createFundamentalComponent'; import createResponder from 'shared/createEventResponder'; import createScope from 'shared/createScope'; -import { - enableJSXTransformAPI, - enableDeprecatedFlareAPI, - enableFundamentalAPI, - enableScopeAPI, - exposeConcurrentModeAPIs, - enableBlocksAPI, - disableCreateFactory, -} from 'shared/ReactFeatureFlags'; -const React = { - Children: { - map, - forEach, - count, - toArray, - only, - }, +// TODO: Move this branching into the other module instead and just re-export. +const createElement = __DEV__ ? createElementWithValidation : createElementProd; +const cloneElement = __DEV__ ? cloneElementWithValidation : cloneElementProd; +const createFactory = __DEV__ ? createFactoryWithValidation : createFactoryProd; + +const jsxDEV = __DEV__ ? jsxWithValidation : undefined; +const jsx = __DEV__ ? jsxWithValidationDynamic : jsxProd; +// we may want to special case jsxs internally to take advantage of static children. +// for now we can ship identical prod functions +const jsxs = __DEV__ ? jsxWithValidationStatic : jsxProd; + +const Children = { + map, + forEach, + count, + toArray, + only, +}; + +export { + Children, createRef, Component, PureComponent, - createContext, forwardRef, lazy, memo, - useCallback, useContext, useEffect, @@ -94,65 +96,34 @@ const React = { useReducer, useRef, useState, - - Fragment: REACT_FRAGMENT_TYPE, - Profiler: REACT_PROFILER_TYPE, - StrictMode: REACT_STRICT_MODE_TYPE, - Suspense: REACT_SUSPENSE_TYPE, - - createElement: __DEV__ ? createElementWithValidation : createElement, - cloneElement: __DEV__ ? cloneElementWithValidation : cloneElement, - isValidElement: isValidElement, - - version: ReactVersion, - - __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: ReactSharedInternals, + REACT_FRAGMENT_TYPE as Fragment, + REACT_PROFILER_TYPE as Profiler, + REACT_STRICT_MODE_TYPE as StrictMode, + REACT_SUSPENSE_TYPE as Suspense, + createElement, + cloneElement, + isValidElement, + ReactVersion as version, + ReactSharedInternals as __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, + // Deprecated behind disableCreateFactory + createFactory, + // Concurrent Mode + useTransition, + useDeferredValue, + REACT_SUSPENSE_LIST_TYPE as SuspenseList, + withSuspenseConfig as unstable_withSuspenseConfig, + // enableBlocksAPI + block, + // enableDeprecatedFlareAPI + useResponder as DEPRECATED_useResponder, + createResponder as DEPRECATED_createResponder, + // enableFundamentalAPI + createFundamental as unstable_createFundamental, + // enableScopeAPI + createScope as unstable_createScope, + // enableJSXTransformAPI + jsx, + jsxs, + // TODO: jsxDEV should not be exposed as a name. We might want to move it to a different entry point. + jsxDEV, }; - -if (!disableCreateFactory) { - React.createFactory = __DEV__ ? createFactoryWithValidation : createFactory; -} - -if (exposeConcurrentModeAPIs) { - React.useTransition = useTransition; - React.useDeferredValue = useDeferredValue; - React.SuspenseList = REACT_SUSPENSE_LIST_TYPE; - React.unstable_withSuspenseConfig = withSuspenseConfig; -} - -if (enableBlocksAPI) { - React.block = block; -} - -if (enableDeprecatedFlareAPI) { - React.DEPRECATED_useResponder = useResponder; - React.DEPRECATED_createResponder = createResponder; -} - -if (enableFundamentalAPI) { - React.unstable_createFundamental = createFundamental; -} - -if (enableScopeAPI) { - React.unstable_createScope = createScope; -} - -// Note: some APIs are added with feature flags. -// Make sure that stable builds for open source -// don't modify the React object to avoid deopts. -// Also let's not expose their names in stable builds. - -if (enableJSXTransformAPI) { - if (__DEV__) { - React.jsxDEV = jsxWithValidation; - React.jsx = jsxWithValidationDynamic; - React.jsxs = jsxWithValidationStatic; - } else { - React.jsx = jsx; - // we may want to special case jsxs internally to take advantage of static children. - // for now we can ship identical prod functions - React.jsxs = jsx; - } -} - -export default React; From 6358b63b7caf52271c54ebebb063da9ebe6c1c66 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Fri, 21 Feb 2020 21:54:31 -0800 Subject: [PATCH 03/12] Export named exports from the export point itself We need to re-export the Flow exported types so we can use them in our code. We don't want to use the Flow types from upstream since it doesn't have the non-public APIs that we have. This should be able to use export * but I don't know why it doesn't work. This actually enables Flow typing of React which was just "any" before. This exposed some Flow errors that needs fixing. --- .../devtools/ContextMenu/useContextMenu.js | 12 ++- .../react-native-renderer/src/ReactFabric.js | 3 +- .../src/ReactFabricHostConfig.js | 4 +- .../src/ReactNativeFiberHostComponent.js | 11 ++- .../src/ReactNativeHostConfig.js | 9 +-- .../src/ReactNativeTypes.js | 4 +- packages/react/index.js | 74 ++++++++++++++++++- packages/shared/ReactSharedInternals.js | 2 + 8 files changed, 97 insertions(+), 22 deletions(-) diff --git a/packages/react-devtools-shared/src/devtools/ContextMenu/useContextMenu.js b/packages/react-devtools-shared/src/devtools/ContextMenu/useContextMenu.js index 1639befc76b..3829a4377ee 100644 --- a/packages/react-devtools-shared/src/devtools/ContextMenu/useContextMenu.js +++ b/packages/react-devtools-shared/src/devtools/ContextMenu/useContextMenu.js @@ -19,18 +19,22 @@ export default function useContextMenu({ }: {| data: Object, id: string, - ref: ElementRef, + ref: {current: ElementRef<'div'> | null}, |}) { const {showMenu} = useContext(RegistryContext); useEffect(() => { if (ref.current !== null) { - const handleContextMenu = event => { + const handleContextMenu = (event: MouseEvent | TouchEvent) => { event.preventDefault(); event.stopPropagation(); - const pageX = event.pageX || (event.touches && event.touches[0].pageX); - const pageY = event.pageY || (event.touches && event.touches[0].pageY); + const pageX = + event.pageX || + (event.touches && ((event: any): TouchEvent).touches[0].pageX); + const pageY = + event.pageY || + (event.touches && ((event: any): TouchEvent).touches[0].pageY); showMenu({data, id, pageX, pageY}); }; diff --git a/packages/react-native-renderer/src/ReactFabric.js b/packages/react-native-renderer/src/ReactFabric.js index 13ae10b1f62..013a4ec77ea 100644 --- a/packages/react-native-renderer/src/ReactFabric.js +++ b/packages/react-native-renderer/src/ReactFabric.js @@ -9,6 +9,7 @@ import type {ReactFabricType, HostComponent} from './ReactNativeTypes'; import type {ReactNodeList} from 'shared/ReactTypes'; +import type {ElementRef} from 'react'; import './ReactFabricInjection'; @@ -43,7 +44,7 @@ const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; function findHostInstance_DEPRECATED( componentOrHandle: any, -): ?React$ElementRef> { +): ?ElementRef> { if (__DEV__) { const owner = ReactCurrentOwner.current; if (owner !== null && owner.stateNode !== null) { diff --git a/packages/react-native-renderer/src/ReactFabricHostConfig.js b/packages/react-native-renderer/src/ReactFabricHostConfig.js index 6e371f9ff8c..4f1b140f8f8 100644 --- a/packages/react-native-renderer/src/ReactFabricHostConfig.js +++ b/packages/react-native-renderer/src/ReactFabricHostConfig.js @@ -7,7 +7,9 @@ * @flow */ +import type {ElementRef} from 'react'; import type { + HostComponent, MeasureInWindowOnSuccessCallback, MeasureLayoutOnSuccessCallback, MeasureOnSuccessCallback, @@ -126,7 +128,7 @@ class ReactFabricHostComponent { } measureLayout( - relativeToNativeNode: number | ReactFabricHostComponent, + relativeToNativeNode: number | ElementRef>, onSuccess: MeasureLayoutOnSuccessCallback, onFail?: () => void /* currently unused */, ) { diff --git a/packages/react-native-renderer/src/ReactNativeFiberHostComponent.js b/packages/react-native-renderer/src/ReactNativeFiberHostComponent.js index c4c74462a4d..f695971f4db 100644 --- a/packages/react-native-renderer/src/ReactNativeFiberHostComponent.js +++ b/packages/react-native-renderer/src/ReactNativeFiberHostComponent.js @@ -7,7 +7,9 @@ * @flow */ +import type {ElementRef} from 'react'; import type { + HostComponent, MeasureInWindowOnSuccessCallback, MeasureLayoutOnSuccessCallback, MeasureOnSuccessCallback, @@ -62,7 +64,7 @@ class ReactNativeFiberHostComponent { } measureLayout( - relativeToNativeNode: number | ReactNativeFiberHostComponent, + relativeToNativeNode: number | ElementRef>, onSuccess: MeasureLayoutOnSuccessCallback, onFail?: () => void /* currently unused */, ) { @@ -71,8 +73,11 @@ class ReactNativeFiberHostComponent { if (typeof relativeToNativeNode === 'number') { // Already a node handle relativeNode = relativeToNativeNode; - } else if (relativeToNativeNode._nativeTag) { - relativeNode = relativeToNativeNode._nativeTag; + } else { + let nativeNode: ReactNativeFiberHostComponent = (relativeToNativeNode: any); + if (nativeNode._nativeTag) { + relativeNode = nativeNode._nativeTag; + } } if (relativeNode == null) { diff --git a/packages/react-native-renderer/src/ReactNativeHostConfig.js b/packages/react-native-renderer/src/ReactNativeHostConfig.js index e91c16a4909..0349591a993 100644 --- a/packages/react-native-renderer/src/ReactNativeHostConfig.js +++ b/packages/react-native-renderer/src/ReactNativeHostConfig.js @@ -7,8 +7,6 @@ * @flow */ -import type {ReactNativeBaseComponentViewConfig} from './ReactNativeTypes'; - import invariant from 'shared/invariant'; // Modules provided by RN: @@ -31,12 +29,7 @@ const {get: getViewConfigForType} = ReactNativeViewConfigRegistry; export type Type = string; export type Props = Object; export type Container = number; -export type Instance = { - _children: Array, - _nativeTag: number, - viewConfig: ReactNativeBaseComponentViewConfig<>, - ... -}; +export type Instance = ReactNativeFiberHostComponent; export type TextInstance = number; export type HydratableInstance = Instance | TextInstance; export type PublicInstance = Instance; diff --git a/packages/react-native-renderer/src/ReactNativeTypes.js b/packages/react-native-renderer/src/ReactNativeTypes.js index 7619625b137..48f89b7d858 100644 --- a/packages/react-native-renderer/src/ReactNativeTypes.js +++ b/packages/react-native-renderer/src/ReactNativeTypes.js @@ -126,7 +126,9 @@ export type ReactNativeType = { }; export type ReactFabricType = { - findHostInstance_DEPRECATED(componentOrHandle: any): ?HostComponent, + findHostInstance_DEPRECATED( + componentOrHandle: any, + ): ?ElementRef>, findNodeHandle(componentOrHandle: any): ?number, dispatchCommand(handle: any, command: string, args: Array): void, render( diff --git a/packages/react/index.js b/packages/react/index.js index 3e2a28ef2bb..c0dd6bbdb3c 100644 --- a/packages/react/index.js +++ b/packages/react/index.js @@ -7,8 +7,74 @@ * @flow */ -'use strict'; +// Keep in sync with https://github.com/facebook/flow/blob/master/lib/react.js +export type StatelessFunctionalComponent< + P, +> = React$StatelessFunctionalComponent

; +export type ComponentType<-P> = React$ComponentType

; +export type AbstractComponent< + -Config, + +Instance = mixed, +> = React$AbstractComponent; +export type ElementType = React$ElementType; +export type Element<+C> = React$Element; +export type Key = React$Key; +export type Ref = React$Ref; +export type Node = React$Node; +export type Context = React$Context; +export type Portal = React$Portal; +export type ElementProps = React$ElementProps; +export type ElementConfig = React$ElementConfig; +export type ElementRef = React$ElementRef; +export type Config = React$Config; +export type ChildrenArray<+T> = $ReadOnlyArray> | T; +export type Interaction = { + name: string, + timestamp: number, + ... +}; -const React = require('./src/React'); - -module.exports = React; +// Export all exports so that they're available in tests. +// We can't use export * from in Flow for some reason. +export { + Children, + createRef, + Component, + PureComponent, + createContext, + forwardRef, + lazy, + memo, + useCallback, + useContext, + useEffect, + useImperativeHandle, + useDebugValue, + useLayoutEffect, + useMemo, + useReducer, + useRef, + useState, + Fragment, + Profiler, + StrictMode, + Suspense, + createElement, + cloneElement, + isValidElement, + version, + __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, + createFactory, + useTransition, + useDeferredValue, + SuspenseList, + unstable_withSuspenseConfig, + block, + DEPRECATED_useResponder, + DEPRECATED_createResponder, + unstable_createFundamental, + unstable_createScope, + jsx, + jsxs, + jsxDEV, +} from './src/React'; diff --git a/packages/shared/ReactSharedInternals.js b/packages/shared/ReactSharedInternals.js index 442b1aac3ec..c0ddf8a8b64 100644 --- a/packages/shared/ReactSharedInternals.js +++ b/packages/shared/ReactSharedInternals.js @@ -3,6 +3,8 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. + * + * @flow */ import * as React from 'react'; From c8bacfc670f039a45e3501e1e2a8c5e06134bf80 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Sat, 22 Feb 2020 00:27:33 -0800 Subject: [PATCH 04/12] Create forks for the react entrypoint None of our builds expose all exports and they all differ in at least one way, so we need four forks. --- packages/react/index.classic.fb.js | 55 ++++++++++++++++++++++++++++ packages/react/index.experimental.js | 46 +++++++++++++++++++++++ packages/react/index.modern.fb.js | 54 +++++++++++++++++++++++++++ packages/react/index.stable.js | 39 ++++++++++++++++++++ 4 files changed, 194 insertions(+) create mode 100644 packages/react/index.classic.fb.js create mode 100644 packages/react/index.experimental.js create mode 100644 packages/react/index.modern.fb.js create mode 100644 packages/react/index.stable.js diff --git a/packages/react/index.classic.fb.js b/packages/react/index.classic.fb.js new file mode 100644 index 00000000000..e0d720efe84 --- /dev/null +++ b/packages/react/index.classic.fb.js @@ -0,0 +1,55 @@ +/** + * 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 + */ + +export { + Children, + createRef, + Component, + PureComponent, + createContext, + forwardRef, + lazy, + memo, + useCallback, + useContext, + useEffect, + useImperativeHandle, + useDebugValue, + useLayoutEffect, + useMemo, + useReducer, + useRef, + useState, + Fragment, + Profiler, + StrictMode, + Suspense, + createElement, + cloneElement, + isValidElement, + version, + __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, + createFactory, + // exposeConcurrentModeAPIs + useTransition, + useDeferredValue, + SuspenseList, + unstable_withSuspenseConfig, + // enableBlocksAPI + block, + // enableDeprecatedFlareAPI + DEPRECATED_useResponder, + DEPRECATED_createResponder, + // enableScopeAPI + unstable_createScope, + // enableJSXTransformAPI + jsx, + jsxs, + jsxDEV, +} from './src/React'; diff --git a/packages/react/index.experimental.js b/packages/react/index.experimental.js new file mode 100644 index 00000000000..e348f332b7f --- /dev/null +++ b/packages/react/index.experimental.js @@ -0,0 +1,46 @@ +/** + * 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 + */ + +export { + Children, + createRef, + Component, + PureComponent, + createContext, + forwardRef, + lazy, + memo, + useCallback, + useContext, + useEffect, + useImperativeHandle, + useDebugValue, + useLayoutEffect, + useMemo, + useReducer, + useRef, + useState, + Fragment, + Profiler, + StrictMode, + Suspense, + createElement, + cloneElement, + isValidElement, + version, + __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, + createFactory, + // exposeConcurrentModeAPIs + useTransition, + useDeferredValue, + SuspenseList, + unstable_withSuspenseConfig, + // enableBlocksAPI + block, +} from './src/React'; diff --git a/packages/react/index.modern.fb.js b/packages/react/index.modern.fb.js new file mode 100644 index 00000000000..0c6ba986e2e --- /dev/null +++ b/packages/react/index.modern.fb.js @@ -0,0 +1,54 @@ +/** + * 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 + */ + +export { + Children, + createRef, + Component, + PureComponent, + createContext, + forwardRef, + lazy, + memo, + useCallback, + useContext, + useEffect, + useImperativeHandle, + useDebugValue, + useLayoutEffect, + useMemo, + useReducer, + useRef, + useState, + Fragment, + Profiler, + StrictMode, + Suspense, + createElement, + cloneElement, + isValidElement, + version, + __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, + // exposeConcurrentModeAPIs + useTransition, + useDeferredValue, + SuspenseList, + unstable_withSuspenseConfig, + // enableBlocksAPI + block, + // enableDeprecatedFlareAPI + DEPRECATED_useResponder, + DEPRECATED_createResponder, + // enableScopeAPI + unstable_createScope, + // enableJSXTransformAPI + jsx, + jsxs, + jsxDEV, +} from './src/React'; diff --git a/packages/react/index.stable.js b/packages/react/index.stable.js new file mode 100644 index 00000000000..67a221ca674 --- /dev/null +++ b/packages/react/index.stable.js @@ -0,0 +1,39 @@ +/** + * 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 + */ + +export { + Children, + createRef, + Component, + PureComponent, + createContext, + forwardRef, + lazy, + memo, + useCallback, + useContext, + useEffect, + useImperativeHandle, + useDebugValue, + useLayoutEffect, + useMemo, + useReducer, + useRef, + useState, + Fragment, + Profiler, + StrictMode, + Suspense, + createElement, + cloneElement, + isValidElement, + version, + __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, + createFactory, +} from './src/React'; From 1f742cac34957ee94c7ad4ff6e1f91cbf3cf7347 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Sat, 22 Feb 2020 00:35:21 -0800 Subject: [PATCH 05/12] Set esModule flag to false We don't want to emit the esModule compatibility flag on our CommonJS output. For now we treat our named exports as if they're CommonJS. This is a potentially breaking change for scheduler (but all those apis are unstable), react-is and use-subscription. However, it seems unlikely that anyone would rely on this since these only have named exports. --- scripts/rollup/build.js | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/scripts/rollup/build.js b/scripts/rollup/build.js index 020a28349ce..2bf93d8e185 100644 --- a/scripts/rollup/build.js +++ b/scripts/rollup/build.js @@ -188,18 +188,16 @@ function getRollupOutputOptions( ) { const isProduction = isProductionBundleType(bundleType); - return Object.assign( - {}, - { - file: outputPath, - format, - globals, - freeze: !isProduction, - interop: false, - name: globalName, - sourcemap: false, - } - ); + return { + file: outputPath, + format, + globals, + freeze: !isProduction, + interop: false, + name: globalName, + sourcemap: false, + esModule: false, + }; } function getFormat(bundleType) { From 981459e88dbb6d2655ce3f182e28221d566a7515 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Sat, 22 Feb 2020 01:19:37 -0800 Subject: [PATCH 06/12] Remove unused Feature Flags --- packages/react-is/src/__tests__/ReactIs-test.js | 4 +--- packages/react/src/__tests__/ReactElement-test.js | 6 ++---- .../react/src/__tests__/ReactElementJSX-test.internal.js | 8 ++------ .../src/__tests__/ReactElementValidator-test.internal.js | 2 +- packages/shared/ReactFeatureFlags.js | 4 ---- packages/shared/forks/ReactFeatureFlags.native-fb.js | 2 -- packages/shared/forks/ReactFeatureFlags.native-oss.js | 2 -- packages/shared/forks/ReactFeatureFlags.persistent.js | 2 -- packages/shared/forks/ReactFeatureFlags.test-renderer.js | 2 -- .../shared/forks/ReactFeatureFlags.test-renderer.www.js | 2 -- packages/shared/forks/ReactFeatureFlags.testing.js | 2 -- packages/shared/forks/ReactFeatureFlags.testing.www.js | 2 -- packages/shared/forks/ReactFeatureFlags.www.js | 4 ---- 13 files changed, 6 insertions(+), 36 deletions(-) diff --git a/packages/react-is/src/__tests__/ReactIs-test.js b/packages/react-is/src/__tests__/ReactIs-test.js index c14ecaf51e1..a56c9f756a1 100644 --- a/packages/react-is/src/__tests__/ReactIs-test.js +++ b/packages/react-is/src/__tests__/ReactIs-test.js @@ -13,8 +13,6 @@ let React; let ReactDOM; let ReactIs; -const ReactFeatureFlags = require('shared/ReactFeatureFlags'); - describe('ReactIs', () => { beforeEach(() => { jest.resetModules(); @@ -56,7 +54,7 @@ describe('ReactIs', () => { expect(ReactIs.isValidElementType(MemoComponent)).toEqual(true); expect(ReactIs.isValidElementType(Context.Provider)).toEqual(true); expect(ReactIs.isValidElementType(Context.Consumer)).toEqual(true); - if (!ReactFeatureFlags.disableCreateFactory) { + if (!__EXPERIMENTAL__) { let factory; expect(() => { factory = React.createFactory('div'); diff --git a/packages/react/src/__tests__/ReactElement-test.js b/packages/react/src/__tests__/ReactElement-test.js index af99767220a..6c3d4f6ceba 100644 --- a/packages/react/src/__tests__/ReactElement-test.js +++ b/packages/react/src/__tests__/ReactElement-test.js @@ -13,8 +13,6 @@ let React; let ReactDOM; let ReactTestUtils; -const ReactFeatureFlags = require('shared/ReactFeatureFlags'); - describe('ReactElement', () => { let ComponentClass; let originalSymbol; @@ -312,7 +310,7 @@ describe('ReactElement', () => { expect(React.isValidElement(true)).toEqual(false); expect(React.isValidElement({})).toEqual(false); expect(React.isValidElement('string')).toEqual(false); - if (!ReactFeatureFlags.disableCreateFactory) { + if (!__EXPERIMENTAL__) { let factory; expect(() => { factory = React.createFactory('div'); @@ -481,7 +479,7 @@ describe('ReactElement', () => { expect(React.isValidElement(true)).toEqual(false); expect(React.isValidElement({})).toEqual(false); expect(React.isValidElement('string')).toEqual(false); - if (!ReactFeatureFlags.disableCreateFactory) { + if (!__EXPERIMENTAL__) { let factory; expect(() => { factory = React.createFactory('div'); diff --git a/packages/react/src/__tests__/ReactElementJSX-test.internal.js b/packages/react/src/__tests__/ReactElementJSX-test.internal.js index cb45ed714b7..6ea12a9e6c2 100644 --- a/packages/react/src/__tests__/ReactElementJSX-test.internal.js +++ b/packages/react/src/__tests__/ReactElementJSX-test.internal.js @@ -31,7 +31,6 @@ describe('ReactElement.jsx', () => { global.Symbol = undefined; ReactFeatureFlags = require('shared/ReactFeatureFlags'); - ReactFeatureFlags.enableJSXTransformAPI = true; ReactFeatureFlags.warnAboutSpreadingKeyToJSX = true; React = require('react'); @@ -69,7 +68,7 @@ describe('ReactElement.jsx', () => { expect(React.isValidElement(true)).toEqual(false); expect(React.isValidElement({})).toEqual(false); expect(React.isValidElement('string')).toEqual(false); - if (!ReactFeatureFlags.disableCreateFactory) { + if (!__EXPERIMENTAL__) { let factory; expect(() => { factory = React.createFactory('div'); @@ -292,9 +291,6 @@ describe('ReactElement.jsx', () => { jest.resetModules(); - ReactFeatureFlags = require('shared/ReactFeatureFlags'); - ReactFeatureFlags.enableJSXTransformAPI = true; - React = require('react'); class Component extends React.Component { @@ -310,7 +306,7 @@ describe('ReactElement.jsx', () => { expect(React.isValidElement(true)).toEqual(false); expect(React.isValidElement({})).toEqual(false); expect(React.isValidElement('string')).toEqual(false); - if (!ReactFeatureFlags.disableCreateFactory) { + if (!__EXPERIMENTAL__) { let factory; expect(() => { factory = React.createFactory('div'); diff --git a/packages/react/src/__tests__/ReactElementValidator-test.internal.js b/packages/react/src/__tests__/ReactElementValidator-test.internal.js index c4016387e15..9380998460c 100644 --- a/packages/react/src/__tests__/ReactElementValidator-test.internal.js +++ b/packages/react/src/__tests__/ReactElementValidator-test.internal.js @@ -439,7 +439,7 @@ describe('ReactElementValidator', () => { ); }); - if (!ReactFeatureFlags.disableCreateFactory) { + if (!__EXPERIMENTAL__) { it('should warn when accessing .type on an element factory', () => { function TestComponent() { return

; diff --git a/packages/shared/ReactFeatureFlags.js b/packages/shared/ReactFeatureFlags.js index eab16bb0793..4ecf7b69d16 100644 --- a/packages/shared/ReactFeatureFlags.js +++ b/packages/shared/ReactFeatureFlags.js @@ -62,7 +62,6 @@ export const enableFundamentalAPI = false; export const enableScopeAPI = false; // New API for JSX transforms to target - https://github.com/reactjs/rfcs/pull/107 -export const enableJSXTransformAPI = false; // We will enforce mocking scheduler with scheduler/unstable_mock at some point. (v17?) // Till then, we warn about the missing mock, but still fallback to a legacy mode compatible version @@ -128,9 +127,6 @@ export const warnAboutStringRefs = false; export const disableLegacyContext = false; -// Disables React.createFactory -export const disableCreateFactory = false; - // Disables hydrate, render, findDOMNode, unmountComponentAtNode export const disableLegacyReactDOMAPIs = false; diff --git a/packages/shared/forks/ReactFeatureFlags.native-fb.js b/packages/shared/forks/ReactFeatureFlags.native-fb.js index 58bf3098dbb..787ebbb602e 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-fb.js +++ b/packages/shared/forks/ReactFeatureFlags.native-fb.js @@ -35,7 +35,6 @@ export const warnAboutDeprecatedLifecycles = true; export const enableDeprecatedFlareAPI = false; export const enableFundamentalAPI = false; export const enableScopeAPI = false; -export const enableJSXTransformAPI = false; export const warnAboutUnmockedScheduler = true; export const flushSuspenseFallbacksInTests = true; export const enableSuspenseCallback = false; @@ -45,7 +44,6 @@ export const disableLegacyContext = false; export const disableSchedulerTimeoutBasedOnReactExpirationTime = false; export const enableTrainModelFix = true; export const enableTrustedTypesIntegration = false; -export const disableCreateFactory = false; export const disableLegacyReactDOMAPIs = false; export const disableTextareaChildren = false; export const disableMapsAsChildren = false; diff --git a/packages/shared/forks/ReactFeatureFlags.native-oss.js b/packages/shared/forks/ReactFeatureFlags.native-oss.js index 91d29d5f5a3..6dece82d185 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-oss.js +++ b/packages/shared/forks/ReactFeatureFlags.native-oss.js @@ -29,7 +29,6 @@ export const enableSchedulerDebugging = false; export const enableDeprecatedFlareAPI = false; export const enableFundamentalAPI = false; export const enableScopeAPI = false; -export const enableJSXTransformAPI = false; export const warnAboutUnmockedScheduler = false; export const flushSuspenseFallbacksInTests = true; export const enableSuspenseCallback = false; @@ -40,7 +39,6 @@ export const disableSchedulerTimeoutBasedOnReactExpirationTime = false; export const enableTrainModelFix = true; export const enableTrustedTypesIntegration = false; export const enableNativeTargetAsInstance = false; -export const disableCreateFactory = false; export const disableLegacyReactDOMAPIs = false; export const disableTextareaChildren = false; export const disableMapsAsChildren = false; diff --git a/packages/shared/forks/ReactFeatureFlags.persistent.js b/packages/shared/forks/ReactFeatureFlags.persistent.js index 05bd97dd2e2..f3c3c0a5069 100644 --- a/packages/shared/forks/ReactFeatureFlags.persistent.js +++ b/packages/shared/forks/ReactFeatureFlags.persistent.js @@ -29,7 +29,6 @@ export const enableSchedulerDebugging = false; export const enableDeprecatedFlareAPI = false; export const enableFundamentalAPI = false; export const enableScopeAPI = false; -export const enableJSXTransformAPI = false; export const warnAboutUnmockedScheduler = true; export const flushSuspenseFallbacksInTests = true; export const enableSuspenseCallback = false; @@ -40,7 +39,6 @@ export const disableSchedulerTimeoutBasedOnReactExpirationTime = false; export const enableTrainModelFix = true; export const enableTrustedTypesIntegration = false; export const enableNativeTargetAsInstance = false; -export const disableCreateFactory = false; export const disableLegacyReactDOMAPIs = false; export const disableTextareaChildren = false; export const disableMapsAsChildren = false; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.js index d1edf59b7ca..af95e4ecc7c 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.js @@ -29,7 +29,6 @@ export const enableSchedulerDebugging = false; export const enableDeprecatedFlareAPI = false; export const enableFundamentalAPI = false; export const enableScopeAPI = false; -export const enableJSXTransformAPI = false; export const warnAboutUnmockedScheduler = false; export const flushSuspenseFallbacksInTests = true; export const enableSuspenseCallback = false; @@ -40,7 +39,6 @@ export const disableSchedulerTimeoutBasedOnReactExpirationTime = false; export const enableTrainModelFix = true; export const enableTrustedTypesIntegration = false; export const enableNativeTargetAsInstance = false; -export const disableCreateFactory = false; export const disableLegacyReactDOMAPIs = false; export const disableTextareaChildren = false; export const disableMapsAsChildren = false; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js index 175bf15fe74..881733ee149 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js @@ -29,7 +29,6 @@ export const disableInputAttributeSyncing = false; export const enableDeprecatedFlareAPI = true; export const enableFundamentalAPI = false; export const enableScopeAPI = true; -export const enableJSXTransformAPI = true; export const warnAboutUnmockedScheduler = true; export const flushSuspenseFallbacksInTests = true; export const enableSuspenseCallback = true; @@ -40,7 +39,6 @@ export const disableSchedulerTimeoutBasedOnReactExpirationTime = false; export const enableTrainModelFix = true; export const enableTrustedTypesIntegration = false; export const enableNativeTargetAsInstance = false; -export const disableCreateFactory = false; export const disableLegacyReactDOMAPIs = false; export const disableTextareaChildren = false; export const disableMapsAsChildren = false; diff --git a/packages/shared/forks/ReactFeatureFlags.testing.js b/packages/shared/forks/ReactFeatureFlags.testing.js index 2969b38630a..84f2ea701be 100644 --- a/packages/shared/forks/ReactFeatureFlags.testing.js +++ b/packages/shared/forks/ReactFeatureFlags.testing.js @@ -29,7 +29,6 @@ export const enableSchedulerDebugging = false; export const enableDeprecatedFlareAPI = false; export const enableFundamentalAPI = false; export const enableScopeAPI = false; -export const enableJSXTransformAPI = false; export const warnAboutUnmockedScheduler = false; export const flushSuspenseFallbacksInTests = true; export const enableSuspenseCallback = false; @@ -40,7 +39,6 @@ export const disableSchedulerTimeoutBasedOnReactExpirationTime = false; export const enableTrainModelFix = true; export const enableTrustedTypesIntegration = false; export const enableNativeTargetAsInstance = false; -export const disableCreateFactory = false; export const disableLegacyReactDOMAPIs = false; export const disableTextareaChildren = false; export const disableMapsAsChildren = false; diff --git a/packages/shared/forks/ReactFeatureFlags.testing.www.js b/packages/shared/forks/ReactFeatureFlags.testing.www.js index 11c5ddbe4e7..8246883d39c 100644 --- a/packages/shared/forks/ReactFeatureFlags.testing.www.js +++ b/packages/shared/forks/ReactFeatureFlags.testing.www.js @@ -29,7 +29,6 @@ export const enableSchedulerDebugging = false; export const enableDeprecatedFlareAPI = true; export const enableFundamentalAPI = false; export const enableScopeAPI = true; -export const enableJSXTransformAPI = true; export const warnAboutUnmockedScheduler = true; export const flushSuspenseFallbacksInTests = true; export const enableSuspenseCallback = true; @@ -40,7 +39,6 @@ export const disableSchedulerTimeoutBasedOnReactExpirationTime = false; export const enableTrainModelFix = true; export const enableTrustedTypesIntegration = false; export const enableNativeTargetAsInstance = false; -export const disableCreateFactory = __EXPERIMENTAL__; export const disableLegacyReactDOMAPIs = __EXPERIMENTAL__; export const disableTextareaChildren = __EXPERIMENTAL__; export const disableMapsAsChildren = __EXPERIMENTAL__; diff --git a/packages/shared/forks/ReactFeatureFlags.www.js b/packages/shared/forks/ReactFeatureFlags.www.js index 2972553b8a8..a1032d3d8d4 100644 --- a/packages/shared/forks/ReactFeatureFlags.www.js +++ b/packages/shared/forks/ReactFeatureFlags.www.js @@ -87,8 +87,6 @@ export const enableFundamentalAPI = false; export const enableScopeAPI = true; -export const enableJSXTransformAPI = true; - export const warnAboutUnmockedScheduler = true; export const enableSuspenseCallback = true; @@ -97,8 +95,6 @@ export const flushSuspenseFallbacksInTests = true; export const enableNativeTargetAsInstance = false; -export const disableCreateFactory = __EXPERIMENTAL__; - export const disableLegacyReactDOMAPIs = __EXPERIMENTAL__; export const disableTextareaChildren = __EXPERIMENTAL__; From f2a2d1177e3717ebee7e315c822f561f497e06a4 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Sat, 22 Feb 2020 02:02:28 -0800 Subject: [PATCH 07/12] Let jest observe the stable fork for stable tests This lets it do the negative test by ensuring that the right tests fail. However, this in turn will make other tests that are not behind __EXPERIMENTAL__ fail. So I need to do that next. --- scripts/jest/config.source-persistent.js | 18 ++++++++++++++++++ scripts/jest/config.source.js | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/scripts/jest/config.source-persistent.js b/scripts/jest/config.source-persistent.js index 935c4463c1c..388d906c2b2 100644 --- a/scripts/jest/config.source-persistent.js +++ b/scripts/jest/config.source-persistent.js @@ -2,7 +2,25 @@ const baseConfig = require('./config.base'); +const RELEASE_CHANNEL = process.env.RELEASE_CHANNEL; + +// Default to building in experimental mode. If the release channel is set via +// an environment variable, then check if it's "experimental". +const __EXPERIMENTAL__ = + typeof RELEASE_CHANNEL === 'string' + ? RELEASE_CHANNEL === 'experimental' + : true; + +const preferredExtension = __EXPERIMENTAL__ ? '.js' : '.stable.js'; + +const moduleNameMapper = {}; +moduleNameMapper[ + '^react$' +] = `/packages/react/index${preferredExtension}`; + module.exports = Object.assign({}, baseConfig, { + // Prefer the stable forks for tests. + moduleNameMapper, modulePathIgnorePatterns: [ ...baseConfig.modulePathIgnorePatterns, 'packages/react-devtools-shared', diff --git a/scripts/jest/config.source.js b/scripts/jest/config.source.js index 2e3401a4ba5..9b3179e0f84 100644 --- a/scripts/jest/config.source.js +++ b/scripts/jest/config.source.js @@ -2,7 +2,25 @@ const baseConfig = require('./config.base'); +const RELEASE_CHANNEL = process.env.RELEASE_CHANNEL; + +// Default to building in experimental mode. If the release channel is set via +// an environment variable, then check if it's "experimental". +const __EXPERIMENTAL__ = + typeof RELEASE_CHANNEL === 'string' + ? RELEASE_CHANNEL === 'experimental' + : true; + +const preferredExtension = __EXPERIMENTAL__ ? '.js' : '.stable.js'; + +const moduleNameMapper = {}; +moduleNameMapper[ + '^react$' +] = `/packages/react/index${preferredExtension}`; + module.exports = Object.assign({}, baseConfig, { + // Prefer the stable forks for tests. + moduleNameMapper, modulePathIgnorePatterns: [ ...baseConfig.modulePathIgnorePatterns, 'packages/react-devtools-shared', From 77a16f275dcf7bad85e72903ff74123b680159e6 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Sun, 23 Feb 2020 15:06:04 -0800 Subject: [PATCH 08/12] Put all tests that depend on exports behind __EXPERIMENTAL__ Since there's no way to override the exports using feature flags in .intern.js anymore we can't use these APIs in stable. The tradeoff here is that we can either enable the negative tests on "stable" that means experimental are expected to fail, or we can disable tests on stable. This is unfortunate since some of these APIs now run on a "stable" config at FB instead of the experimental. --- .../ReactHooksInspection-test.internal.js | 5 + ...DOMServerPartialHydration-test.internal.js | 196 ++++----- ...MServerSelectiveHydration-test.internal.js | 372 +++++++++--------- ...edDOMEventResponderSystem-test.internal.js | 5 + .../__tests__/ContextMenu-test.internal.js | 5 + .../src/dom/__tests__/Focus-test.internal.js | 5 + .../__tests__/FocusWithin-test.internal.js | 5 + .../src/dom/__tests__/Hover-test.internal.js | 5 + .../src/dom/__tests__/Input-test.internal.js | 5 + .../dom/__tests__/Keyboard-test.internal.js | 5 + .../MixedResponders-test-internal.js | 5 + .../src/dom/__tests__/Press-test.internal.js | 5 + .../__tests__/PressLegacy-test.internal.js | 5 + .../src/dom/__tests__/Tap-test.internal.js | 5 + .../ReactFiberFundamental-test.internal.js | 5 + .../src/__tests__/ReactScope-test.internal.js | 5 + .../ReactElementJSX-test.internal.js | 5 + 17 files changed, 362 insertions(+), 281 deletions(-) diff --git a/packages/react-debug-tools/src/__tests__/ReactHooksInspection-test.internal.js b/packages/react-debug-tools/src/__tests__/ReactHooksInspection-test.internal.js index 3e1c67087c1..d075b7097de 100644 --- a/packages/react-debug-tools/src/__tests__/ReactHooksInspection-test.internal.js +++ b/packages/react-debug-tools/src/__tests__/ReactHooksInspection-test.internal.js @@ -22,6 +22,11 @@ describe('ReactHooksInspection', () => { ReactDebugTools = require('react-debug-tools'); }); + if (!__EXPERIMENTAL__) { + it("empty test so Jest doesn't complain", () => {}); + return; + } + it('should inspect a simple useResponder hook', () => { const TestResponder = React.DEPRECATED_createResponder('TestResponder', {}); diff --git a/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js b/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js index 7a25979987b..f6f7c4979bc 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js @@ -86,8 +86,6 @@ describe('ReactDOMServerPartialHydration', () => { Scheduler = require('scheduler'); Suspense = React.Suspense; SuspenseList = React.SuspenseList; - - useHover = require('react-interactions/events/hover').useHover; }); if (!__EXPERIMENTAL__) { @@ -2368,120 +2366,124 @@ describe('ReactDOMServerPartialHydration', () => { document.body.removeChild(container); }); - it('blocks only on the last continuous event (Responder system)', async () => { - let suspend1 = false; - let resolve1; - let promise1 = new Promise(resolvePromise => (resolve1 = resolvePromise)); - let suspend2 = false; - let resolve2; - let promise2 = new Promise(resolvePromise => (resolve2 = resolvePromise)); - - function First({text}) { - if (suspend1) { - throw promise1; - } else { - return 'Hello'; + if (__EXPERIMENTAL__) { + it('blocks only on the last continuous event (Responder system)', async () => { + useHover = require('react-interactions/events/hover').useHover; + + let suspend1 = false; + let resolve1; + let promise1 = new Promise(resolvePromise => (resolve1 = resolvePromise)); + let suspend2 = false; + let resolve2; + let promise2 = new Promise(resolvePromise => (resolve2 = resolvePromise)); + + function First({text}) { + if (suspend1) { + throw promise1; + } else { + return 'Hello'; + } } - } - function Second({text}) { - if (suspend2) { - throw promise2; - } else { - return 'World'; + function Second({text}) { + if (suspend2) { + throw promise2; + } else { + return 'World'; + } } - } - - let ops = []; - function App() { - const listener1 = useHover({ - onHoverStart() { - ops.push('Hover Start First'); - }, - onHoverEnd() { - ops.push('Hover End First'); - }, - }); - const listener2 = useHover({ - onHoverStart() { - ops.push('Hover Start Second'); - }, - onHoverEnd() { - ops.push('Hover End Second'); - }, - }); - return ( -
- - - {/* We suspend after to test what happens when we eager + let ops = []; + + function App() { + const listener1 = useHover({ + onHoverStart() { + ops.push('Hover Start First'); + }, + onHoverEnd() { + ops.push('Hover End First'); + }, + }); + const listener2 = useHover({ + onHoverStart() { + ops.push('Hover Start Second'); + }, + onHoverEnd() { + ops.push('Hover End Second'); + }, + }); + return ( +
+ + + {/* We suspend after to test what happens when we eager attach the listener. */} - - - - - - - -
- ); - } + +
+ + + + + +
+ ); + } - let finalHTML = ReactDOMServer.renderToString(); - let container = document.createElement('div'); - container.innerHTML = finalHTML; + let finalHTML = ReactDOMServer.renderToString(); + let container = document.createElement('div'); + container.innerHTML = finalHTML; - // We need this to be in the document since we'll dispatch events on it. - document.body.appendChild(container); + // We need this to be in the document since we'll dispatch events on it. + document.body.appendChild(container); - let appDiv = container.getElementsByTagName('div')[0]; - let firstSpan = appDiv.getElementsByTagName('span')[0]; - let secondSpan = appDiv.getElementsByTagName('span')[1]; - expect(firstSpan.textContent).toBe(''); - expect(secondSpan.textContent).toBe('World'); + let appDiv = container.getElementsByTagName('div')[0]; + let firstSpan = appDiv.getElementsByTagName('span')[0]; + let secondSpan = appDiv.getElementsByTagName('span')[1]; + expect(firstSpan.textContent).toBe(''); + expect(secondSpan.textContent).toBe('World'); - // On the client we don't have all data yet but we want to start - // hydrating anyway. - suspend1 = true; - suspend2 = true; - let root = ReactDOM.createRoot(container, {hydrate: true}); - root.render(); + // On the client we don't have all data yet but we want to start + // hydrating anyway. + suspend1 = true; + suspend2 = true; + let root = ReactDOM.createRoot(container, {hydrate: true}); + root.render(); - Scheduler.unstable_flushAll(); - jest.runAllTimers(); + Scheduler.unstable_flushAll(); + jest.runAllTimers(); - dispatchMouseEvent(appDiv, null); - dispatchMouseEvent(firstSpan, appDiv); - dispatchMouseEvent(secondSpan, firstSpan); + dispatchMouseEvent(appDiv, null); + dispatchMouseEvent(firstSpan, appDiv); + dispatchMouseEvent(secondSpan, firstSpan); - // Neither target is yet hydrated. - expect(ops).toEqual([]); + // Neither target is yet hydrated. + expect(ops).toEqual([]); - // Resolving the second promise so that rendering can complete. - suspend2 = false; - resolve2(); - await promise2; + // Resolving the second promise so that rendering can complete. + suspend2 = false; + resolve2(); + await promise2; - Scheduler.unstable_flushAll(); - jest.runAllTimers(); + Scheduler.unstable_flushAll(); + jest.runAllTimers(); - // We've unblocked the current hover target so we should be - // able to replay it now. - expect(ops).toEqual(['Hover Start Second']); + // We've unblocked the current hover target so we should be + // able to replay it now. + expect(ops).toEqual(['Hover Start Second']); - // Resolving the first promise has no effect now. - suspend1 = false; - resolve1(); - await promise1; + // Resolving the first promise has no effect now. + suspend1 = false; + resolve1(); + await promise1; - Scheduler.unstable_flushAll(); - jest.runAllTimers(); + Scheduler.unstable_flushAll(); + jest.runAllTimers(); - expect(ops).toEqual(['Hover Start Second']); + expect(ops).toEqual(['Hover Start Second']); - document.body.removeChild(container); - }); + document.body.removeChild(container); + }); + } it('finishes normal pri work before continuing to hydrate a retry', async () => { let suspend = false; diff --git a/packages/react-dom/src/__tests__/ReactDOMServerSelectiveHydration-test.internal.js b/packages/react-dom/src/__tests__/ReactDOMServerSelectiveHydration-test.internal.js index 02d1dff1a9e..3fb9169c1dc 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerSelectiveHydration-test.internal.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerSelectiveHydration-test.internal.js @@ -17,7 +17,6 @@ let ReactDOMServer; let ReactTestUtils; let Scheduler; let Suspense; -let usePress; function dispatchMouseHoverEvent(to, from) { if (!to) { @@ -106,7 +105,6 @@ describe('ReactDOMServerSelectiveHydration', () => { ReactTestUtils = require('react-dom/test-utils'); Scheduler = require('scheduler'); Suspense = React.Suspense; - usePress = require('react-interactions/events/press').usePress; }); if (!__EXPERIMENTAL__) { @@ -352,240 +350,246 @@ describe('ReactDOMServerSelectiveHydration', () => { document.body.removeChild(container); }); - it('hydrates the target boundary synchronously during a click (flare)', async () => { - function Child({text}) { - Scheduler.unstable_yieldValue(text); - const listener = usePress({ - onPress() { - Scheduler.unstable_yieldValue('Clicked ' + text); - }, - }); + if (__EXPERIMENTAL__) { + it('hydrates the target boundary synchronously during a click (flare)', async () => { + let usePress = require('react-interactions/events/press').usePress; - return {text}; - } + function Child({text}) { + Scheduler.unstable_yieldValue(text); + const listener = usePress({ + onPress() { + Scheduler.unstable_yieldValue('Clicked ' + text); + }, + }); - function App() { - Scheduler.unstable_yieldValue('App'); - return ( -
- - - - - - -
- ); - } + return {text}; + } - let finalHTML = ReactDOMServer.renderToString(); + function App() { + Scheduler.unstable_yieldValue('App'); + return ( +
+ + + + + + +
+ ); + } - expect(Scheduler).toHaveYielded(['App', 'A', 'B']); + let finalHTML = ReactDOMServer.renderToString(); - let container = document.createElement('div'); - // We need this to be in the document since we'll dispatch events on it. - document.body.appendChild(container); + expect(Scheduler).toHaveYielded(['App', 'A', 'B']); - container.innerHTML = finalHTML; + let container = document.createElement('div'); + // We need this to be in the document since we'll dispatch events on it. + document.body.appendChild(container); - let root = ReactDOM.createRoot(container, {hydrate: true}); - root.render(); + container.innerHTML = finalHTML; - // Nothing has been hydrated so far. - expect(Scheduler).toHaveYielded([]); + let root = ReactDOM.createRoot(container, {hydrate: true}); + root.render(); - let span = container.getElementsByTagName('span')[1]; + // Nothing has been hydrated so far. + expect(Scheduler).toHaveYielded([]); - let target = createEventTarget(span); + let span = container.getElementsByTagName('span')[1]; - // This should synchronously hydrate the root App and the second suspense - // boundary. - let preventDefault = jest.fn(); - target.virtualclick({preventDefault}); + let target = createEventTarget(span); - // The event should have been canceled because we called preventDefault. - expect(preventDefault).toHaveBeenCalled(); + // This should synchronously hydrate the root App and the second suspense + // boundary. + let preventDefault = jest.fn(); + target.virtualclick({preventDefault}); - // We rendered App, B and then invoked the event without rendering A. - expect(Scheduler).toHaveYielded(['App', 'B', 'Clicked B']); + // The event should have been canceled because we called preventDefault. + expect(preventDefault).toHaveBeenCalled(); - // After continuing the scheduler, we finally hydrate A. - expect(Scheduler).toFlushAndYield(['A']); + // We rendered App, B and then invoked the event without rendering A. + expect(Scheduler).toHaveYielded(['App', 'B', 'Clicked B']); - document.body.removeChild(container); - }); + // After continuing the scheduler, we finally hydrate A. + expect(Scheduler).toFlushAndYield(['A']); - it('hydrates at higher pri if sync did not work first time (flare)', async () => { - let suspend = false; - let resolve; - let promise = new Promise(resolvePromise => (resolve = resolvePromise)); + document.body.removeChild(container); + }); - function Child({text}) { - if ((text === 'A' || text === 'D') && suspend) { - throw promise; + it('hydrates at higher pri if sync did not work first time (flare)', async () => { + let usePress = require('react-interactions/events/press').usePress; + let suspend = false; + let resolve; + let promise = new Promise(resolvePromise => (resolve = resolvePromise)); + + function Child({text}) { + if ((text === 'A' || text === 'D') && suspend) { + throw promise; + } + Scheduler.unstable_yieldValue(text); + + const listener = usePress({ + onPress() { + Scheduler.unstable_yieldValue('Clicked ' + text); + }, + }); + return {text}; } - Scheduler.unstable_yieldValue(text); - const listener = usePress({ - onPress() { - Scheduler.unstable_yieldValue('Clicked ' + text); - }, - }); - return {text}; - } + function App() { + Scheduler.unstable_yieldValue('App'); + return ( +
+ + + + + + + + + + + + +
+ ); + } - function App() { - Scheduler.unstable_yieldValue('App'); - return ( -
- - - - - - - - - - - - -
- ); - } + let finalHTML = ReactDOMServer.renderToString(); - let finalHTML = ReactDOMServer.renderToString(); + expect(Scheduler).toHaveYielded(['App', 'A', 'B', 'C', 'D']); - expect(Scheduler).toHaveYielded(['App', 'A', 'B', 'C', 'D']); + let container = document.createElement('div'); + // We need this to be in the document since we'll dispatch events on it. + document.body.appendChild(container); - let container = document.createElement('div'); - // We need this to be in the document since we'll dispatch events on it. - document.body.appendChild(container); + container.innerHTML = finalHTML; - container.innerHTML = finalHTML; + let spanD = container.getElementsByTagName('span')[3]; - let spanD = container.getElementsByTagName('span')[3]; + suspend = true; - suspend = true; + // A and D will be suspended. We'll click on D which should take + // priority, after we unsuspend. + let root = ReactDOM.createRoot(container, {hydrate: true}); + root.render(); - // A and D will be suspended. We'll click on D which should take - // priority, after we unsuspend. - let root = ReactDOM.createRoot(container, {hydrate: true}); - root.render(); + // Nothing has been hydrated so far. + expect(Scheduler).toHaveYielded([]); - // Nothing has been hydrated so far. - expect(Scheduler).toHaveYielded([]); + // This click target cannot be hydrated yet because it's suspended. + let result = dispatchClickEvent(spanD); - // This click target cannot be hydrated yet because it's suspended. - let result = dispatchClickEvent(spanD); + expect(Scheduler).toHaveYielded(['App']); - expect(Scheduler).toHaveYielded(['App']); + expect(result).toBe(true); - expect(result).toBe(true); + // Continuing rendering will render B next. + expect(Scheduler).toFlushAndYield(['B', 'C']); - // Continuing rendering will render B next. - expect(Scheduler).toFlushAndYield(['B', 'C']); + suspend = false; + resolve(); + await promise; - suspend = false; - resolve(); - await promise; + // After the click, we should prioritize D and the Click first, + // and only after that render A and C. + expect(Scheduler).toFlushAndYield(['D', 'Clicked D', 'A']); - // After the click, we should prioritize D and the Click first, - // and only after that render A and C. - expect(Scheduler).toFlushAndYield(['D', 'Clicked D', 'A']); + document.body.removeChild(container); + }); - document.body.removeChild(container); - }); + it('hydrates at higher pri for secondary discrete events (flare)', async () => { + let usePress = require('react-interactions/events/press').usePress; + let suspend = false; + let resolve; + let promise = new Promise(resolvePromise => (resolve = resolvePromise)); - it('hydrates at higher pri for secondary discrete events (flare)', async () => { - let suspend = false; - let resolve; - let promise = new Promise(resolvePromise => (resolve = resolvePromise)); + function Child({text}) { + if ((text === 'A' || text === 'D') && suspend) { + throw promise; + } + Scheduler.unstable_yieldValue(text); - function Child({text}) { - if ((text === 'A' || text === 'D') && suspend) { - throw promise; + const listener = usePress({ + onPress() { + Scheduler.unstable_yieldValue('Clicked ' + text); + }, + }); + return {text}; } - Scheduler.unstable_yieldValue(text); - const listener = usePress({ - onPress() { - Scheduler.unstable_yieldValue('Clicked ' + text); - }, - }); - return {text}; - } + function App() { + Scheduler.unstable_yieldValue('App'); + return ( +
+ + + + + + + + + + + + +
+ ); + } - function App() { - Scheduler.unstable_yieldValue('App'); - return ( -
- - - - - - - - - - - - -
- ); - } + let finalHTML = ReactDOMServer.renderToString(); - let finalHTML = ReactDOMServer.renderToString(); + expect(Scheduler).toHaveYielded(['App', 'A', 'B', 'C', 'D']); - expect(Scheduler).toHaveYielded(['App', 'A', 'B', 'C', 'D']); + let container = document.createElement('div'); + // We need this to be in the document since we'll dispatch events on it. + document.body.appendChild(container); - let container = document.createElement('div'); - // We need this to be in the document since we'll dispatch events on it. - document.body.appendChild(container); + container.innerHTML = finalHTML; - container.innerHTML = finalHTML; + let spanA = container.getElementsByTagName('span')[0]; + let spanC = container.getElementsByTagName('span')[2]; + let spanD = container.getElementsByTagName('span')[3]; - let spanA = container.getElementsByTagName('span')[0]; - let spanC = container.getElementsByTagName('span')[2]; - let spanD = container.getElementsByTagName('span')[3]; + suspend = true; - suspend = true; + // A and D will be suspended. We'll click on D which should take + // priority, after we unsuspend. + let root = ReactDOM.createRoot(container, {hydrate: true}); + root.render(); - // A and D will be suspended. We'll click on D which should take - // priority, after we unsuspend. - let root = ReactDOM.createRoot(container, {hydrate: true}); - root.render(); + // Nothing has been hydrated so far. + expect(Scheduler).toHaveYielded([]); - // Nothing has been hydrated so far. - expect(Scheduler).toHaveYielded([]); + // This click target cannot be hydrated yet because the first is Suspended. + dispatchClickEvent(spanA); + dispatchClickEvent(spanC); + dispatchClickEvent(spanD); - // This click target cannot be hydrated yet because the first is Suspended. - dispatchClickEvent(spanA); - dispatchClickEvent(spanC); - dispatchClickEvent(spanD); + expect(Scheduler).toHaveYielded(['App']); - expect(Scheduler).toHaveYielded(['App']); + suspend = false; + resolve(); + await promise; - suspend = false; - resolve(); - await promise; - - // We should prioritize hydrating A, C and D first since we clicked in - // them. Only after they're done will we hydrate B. - expect(Scheduler).toFlushAndYield([ - 'A', - 'Clicked A', - 'C', - 'Clicked C', - 'D', - 'Clicked D', - // B should render last since it wasn't clicked. - 'B', - ]); + // We should prioritize hydrating A, C and D first since we clicked in + // them. Only after they're done will we hydrate B. + expect(Scheduler).toFlushAndYield([ + 'A', + 'Clicked A', + 'C', + 'Clicked C', + 'D', + 'Clicked D', + // B should render last since it wasn't clicked. + 'B', + ]); - document.body.removeChild(container); - }); + document.body.removeChild(container); + }); + } it('hydrates the hovered targets as higher priority for continuous events', async () => { let suspend = false; diff --git a/packages/react-dom/src/events/__tests__/DeprecatedDOMEventResponderSystem-test.internal.js b/packages/react-dom/src/events/__tests__/DeprecatedDOMEventResponderSystem-test.internal.js index 3711cbe3036..c3fa398e837 100644 --- a/packages/react-dom/src/events/__tests__/DeprecatedDOMEventResponderSystem-test.internal.js +++ b/packages/react-dom/src/events/__tests__/DeprecatedDOMEventResponderSystem-test.internal.js @@ -66,6 +66,11 @@ function dispatchClickEvent(element) { describe('DOMEventResponderSystem', () => { let container; + if (!__EXPERIMENTAL__) { + it("empty test so Jest doesn't complain", () => {}); + return; + } + beforeEach(() => { jest.resetModules(); ReactFeatureFlags = require('shared/ReactFeatureFlags'); diff --git a/packages/react-interactions/events/src/dom/__tests__/ContextMenu-test.internal.js b/packages/react-interactions/events/src/dom/__tests__/ContextMenu-test.internal.js index f57d4164597..affcf8e6fbf 100644 --- a/packages/react-interactions/events/src/dom/__tests__/ContextMenu-test.internal.js +++ b/packages/react-interactions/events/src/dom/__tests__/ContextMenu-test.internal.js @@ -38,6 +38,11 @@ const table = [[forcePointerEvents], [!forcePointerEvents]]; describe.each(table)('ContextMenu responder', hasPointerEvents => { let container; + if (!__EXPERIMENTAL__) { + it("empty test so Jest doesn't complain", () => {}); + return; + } + beforeEach(() => { initializeModules(hasPointerEvents); container = document.createElement('div'); diff --git a/packages/react-interactions/events/src/dom/__tests__/Focus-test.internal.js b/packages/react-interactions/events/src/dom/__tests__/Focus-test.internal.js index 66946f07abc..0b751d5c063 100644 --- a/packages/react-interactions/events/src/dom/__tests__/Focus-test.internal.js +++ b/packages/react-interactions/events/src/dom/__tests__/Focus-test.internal.js @@ -38,6 +38,11 @@ const table = [[forcePointerEvents], [!forcePointerEvents]]; describe.each(table)('Focus responder', hasPointerEvents => { let container; + if (!__EXPERIMENTAL__) { + it("empty test so Jest doesn't complain", () => {}); + return; + } + beforeEach(() => { initializeModules(hasPointerEvents); container = document.createElement('div'); diff --git a/packages/react-interactions/events/src/dom/__tests__/FocusWithin-test.internal.js b/packages/react-interactions/events/src/dom/__tests__/FocusWithin-test.internal.js index 647527e4e44..6d474b429bd 100644 --- a/packages/react-interactions/events/src/dom/__tests__/FocusWithin-test.internal.js +++ b/packages/react-interactions/events/src/dom/__tests__/FocusWithin-test.internal.js @@ -37,6 +37,11 @@ const table = [[forcePointerEvents], [!forcePointerEvents]]; describe.each(table)('FocusWithin responder', hasPointerEvents => { let container; + if (!__EXPERIMENTAL__) { + it("empty test so Jest doesn't complain", () => {}); + return; + } + beforeEach(() => { initializeModules(); container = document.createElement('div'); diff --git a/packages/react-interactions/events/src/dom/__tests__/Hover-test.internal.js b/packages/react-interactions/events/src/dom/__tests__/Hover-test.internal.js index 06437852b45..35f71ebabaf 100644 --- a/packages/react-interactions/events/src/dom/__tests__/Hover-test.internal.js +++ b/packages/react-interactions/events/src/dom/__tests__/Hover-test.internal.js @@ -34,6 +34,11 @@ const table = [[forcePointerEvents], [!forcePointerEvents]]; describe.each(table)('Hover responder', hasPointerEvents => { let container; + if (!__EXPERIMENTAL__) { + it("empty test so Jest doesn't complain", () => {}); + return; + } + beforeEach(() => { initializeModules(hasPointerEvents); container = document.createElement('div'); diff --git a/packages/react-interactions/events/src/dom/__tests__/Input-test.internal.js b/packages/react-interactions/events/src/dom/__tests__/Input-test.internal.js index cf1bb6670f5..5248e58a067 100644 --- a/packages/react-interactions/events/src/dom/__tests__/Input-test.internal.js +++ b/packages/react-interactions/events/src/dom/__tests__/Input-test.internal.js @@ -45,6 +45,11 @@ const modulesInit = () => { describe('Input event responder', () => { let container; + if (!__EXPERIMENTAL__) { + it("empty test so Jest doesn't complain", () => {}); + return; + } + beforeEach(() => { jest.resetModules(); modulesInit(); diff --git a/packages/react-interactions/events/src/dom/__tests__/Keyboard-test.internal.js b/packages/react-interactions/events/src/dom/__tests__/Keyboard-test.internal.js index 68a69dfba6c..bd649765d5e 100644 --- a/packages/react-interactions/events/src/dom/__tests__/Keyboard-test.internal.js +++ b/packages/react-interactions/events/src/dom/__tests__/Keyboard-test.internal.js @@ -28,6 +28,11 @@ function initializeModules(hasPointerEvents) { describe('Keyboard responder', () => { let container; + if (!__EXPERIMENTAL__) { + it("empty test so Jest doesn't complain", () => {}); + return; + } + beforeEach(() => { initializeModules(); container = document.createElement('div'); diff --git a/packages/react-interactions/events/src/dom/__tests__/MixedResponders-test-internal.js b/packages/react-interactions/events/src/dom/__tests__/MixedResponders-test-internal.js index aeb265329ed..6dc3ee24ec7 100644 --- a/packages/react-interactions/events/src/dom/__tests__/MixedResponders-test-internal.js +++ b/packages/react-interactions/events/src/dom/__tests__/MixedResponders-test-internal.js @@ -19,6 +19,11 @@ let Scheduler; describe('mixing responders with the heritage event system', () => { let container; + if (!__EXPERIMENTAL__) { + it("empty test so Jest doesn't complain", () => {}); + return; + } + beforeEach(() => { ReactFeatureFlags = require('shared/ReactFeatureFlags'); ReactFeatureFlags.enableDeprecatedFlareAPI = true; diff --git a/packages/react-interactions/events/src/dom/__tests__/Press-test.internal.js b/packages/react-interactions/events/src/dom/__tests__/Press-test.internal.js index 6987280090a..e9245fbb53b 100644 --- a/packages/react-interactions/events/src/dom/__tests__/Press-test.internal.js +++ b/packages/react-interactions/events/src/dom/__tests__/Press-test.internal.js @@ -38,6 +38,11 @@ const pointerTypesTable = [['mouse'], ['touch']]; describeWithPointerEvent('Press responder', hasPointerEvents => { let container; + if (!__EXPERIMENTAL__) { + it("empty test so Jest doesn't complain", () => {}); + return; + } + beforeEach(() => { initializeModules(hasPointerEvents); container = document.createElement('div'); diff --git a/packages/react-interactions/events/src/dom/__tests__/PressLegacy-test.internal.js b/packages/react-interactions/events/src/dom/__tests__/PressLegacy-test.internal.js index 65cb1141f8b..381fed4a7fa 100644 --- a/packages/react-interactions/events/src/dom/__tests__/PressLegacy-test.internal.js +++ b/packages/react-interactions/events/src/dom/__tests__/PressLegacy-test.internal.js @@ -50,6 +50,11 @@ const pointerTypesTable = [['mouse'], ['touch']]; describe.each(environmentTable)('Press responder', hasPointerEvents => { let container; + if (!__EXPERIMENTAL__) { + it("empty test so Jest doesn't complain", () => {}); + return; + } + beforeEach(() => { initializeModules(hasPointerEvents); container = document.createElement('div'); diff --git a/packages/react-interactions/events/src/dom/__tests__/Tap-test.internal.js b/packages/react-interactions/events/src/dom/__tests__/Tap-test.internal.js index 39fd5d06f9b..17c550a2483 100644 --- a/packages/react-interactions/events/src/dom/__tests__/Tap-test.internal.js +++ b/packages/react-interactions/events/src/dom/__tests__/Tap-test.internal.js @@ -73,6 +73,11 @@ function tapAndReleaseOutside({ describeWithPointerEvent('Tap responder', hasPointerEvents => { let container; + if (!__EXPERIMENTAL__) { + it("empty test so Jest doesn't complain", () => {}); + return; + } + beforeEach(() => { initializeModules(hasPointerEvents); container = document.createElement('div'); diff --git a/packages/react-reconciler/src/__tests__/ReactFiberFundamental-test.internal.js b/packages/react-reconciler/src/__tests__/ReactFiberFundamental-test.internal.js index 00b00b533b9..081b0be2d38 100644 --- a/packages/react-reconciler/src/__tests__/ReactFiberFundamental-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactFiberFundamental-test.internal.js @@ -50,6 +50,11 @@ function initReactDOMServer() { } describe('ReactFiberFundamental', () => { + if (!__EXPERIMENTAL__) { + it("empty test so Jest doesn't complain", () => {}); + return; + } + describe('NoopRenderer', () => { beforeEach(() => { initNoopRenderer(); diff --git a/packages/react-reconciler/src/__tests__/ReactScope-test.internal.js b/packages/react-reconciler/src/__tests__/ReactScope-test.internal.js index 8144a11be82..78b863e9951 100644 --- a/packages/react-reconciler/src/__tests__/ReactScope-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactScope-test.internal.js @@ -23,6 +23,11 @@ describe('ReactScope', () => { React = require('react'); }); + if (!__EXPERIMENTAL__) { + it("empty test so Jest doesn't complain", () => {}); + return; + } + describe('ReactDOM', () => { let ReactDOM; let container; diff --git a/packages/react/src/__tests__/ReactElementJSX-test.internal.js b/packages/react/src/__tests__/ReactElementJSX-test.internal.js index 6ea12a9e6c2..4a02bbc1a37 100644 --- a/packages/react/src/__tests__/ReactElementJSX-test.internal.js +++ b/packages/react/src/__tests__/ReactElementJSX-test.internal.js @@ -42,6 +42,11 @@ describe('ReactElement.jsx', () => { global.Symbol = originalSymbol; }); + if (!__EXPERIMENTAL__) { + it("empty test so Jest doesn't complain", () => {}); + return; + } + it('allows static methods to be called using the type property', () => { class StaticMethodComponentClass extends React.Component { render() { From a96f367f7f5f784a809da30972f6e66a7f7a0775 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Sun, 23 Feb 2020 15:51:21 -0800 Subject: [PATCH 09/12] Switch ReactDOM to named exports Same strategy as React. I moved the ReactDOMFB runtime injection to classic.fb.js Since we only fork the entrypoint, the `/testing` entrypoint needs to be forked too to re-export the same things plus `act`. This is a bit unfortunate. If it becomes a pattern we can consider forking in the module resolution deeply. fix flow --- packages/react-dom/index.classic.fb.js | 46 +++++ packages/react-dom/index.experimental.js | 34 ++++ packages/react-dom/index.fb.js | 14 -- packages/react-dom/index.js | 8 +- packages/react-dom/index.modern.fb.js | 22 +++ packages/react-dom/index.stable.js | 24 +++ packages/react-dom/src/client/ReactDOM.js | 182 ++++++++++---------- packages/react-dom/src/client/ReactDOMFB.js | 36 ---- packages/react-dom/testing.classic.fb.js | 11 ++ packages/react-dom/testing.experimental.js | 11 ++ packages/react-dom/testing.js | 9 +- packages/react-dom/testing.modern.fb.js | 11 ++ packages/react-dom/testing.stable.js | 11 ++ 13 files changed, 261 insertions(+), 158 deletions(-) create mode 100644 packages/react-dom/index.classic.fb.js create mode 100644 packages/react-dom/index.experimental.js delete mode 100644 packages/react-dom/index.fb.js create mode 100644 packages/react-dom/index.modern.fb.js create mode 100644 packages/react-dom/index.stable.js delete mode 100644 packages/react-dom/src/client/ReactDOMFB.js create mode 100644 packages/react-dom/testing.classic.fb.js create mode 100644 packages/react-dom/testing.experimental.js create mode 100644 packages/react-dom/testing.modern.fb.js create mode 100644 packages/react-dom/testing.stable.js diff --git a/packages/react-dom/index.classic.fb.js b/packages/react-dom/index.classic.fb.js new file mode 100644 index 00000000000..96ce6a6cc35 --- /dev/null +++ b/packages/react-dom/index.classic.fb.js @@ -0,0 +1,46 @@ +/** + * 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 + */ + +import {addUserTimingListener} from 'shared/ReactFeatureFlags'; +import {isEnabled} from './src/events/ReactDOMEventListener'; +import {getClosestInstanceFromNode} from './src/client/ReactDOMComponentTree'; + +import {__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED} from './src/client/ReactDOM'; + +// For classic WWW builds, include a few internals that are already in use. +Object.assign((__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: any), { + ReactBrowserEventEmitter: { + isEnabled, + }, + ReactDOMComponentTree: { + getClosestInstanceFromNode, + }, + // Perf experiment + addUserTimingListener, +}); + +export { + createPortal, + unstable_batchedUpdates, + flushSync, + __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, + version, + findDOMNode, + hydrate, + render, + unmountComponentAtNode, + createRoot, + createBlockingRoot, + unstable_discreteUpdates, + unstable_flushDiscreteUpdates, + unstable_flushControlled, + unstable_scheduleHydration, + unstable_renderSubtreeIntoContainer, + unstable_createPortal, +} from './src/client/ReactDOM'; diff --git a/packages/react-dom/index.experimental.js b/packages/react-dom/index.experimental.js new file mode 100644 index 00000000000..b771d0105b8 --- /dev/null +++ b/packages/react-dom/index.experimental.js @@ -0,0 +1,34 @@ +/** + * 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 + */ + +export { + createPortal, + unstable_batchedUpdates, + flushSync, + __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, + version, + // Disabled behind disableLegacyReactDOMAPIs + findDOMNode, + hydrate, + render, + unmountComponentAtNode, + // exposeConcurrentModeAPIs + createRoot, + createBlockingRoot, + unstable_discreteUpdates, + unstable_flushDiscreteUpdates, + unstable_flushControlled, + unstable_scheduleHydration, + // Disabled behind disableUnstableRenderSubtreeIntoContainer + unstable_renderSubtreeIntoContainer, + // Disabled behind disableUnstableCreatePortal + // Temporary alias since we already shipped React 16 RC with it. + // TODO: remove in React 17. + unstable_createPortal, +} from './src/client/ReactDOM'; diff --git a/packages/react-dom/index.fb.js b/packages/react-dom/index.fb.js deleted file mode 100644 index ea901748d69..00000000000 --- a/packages/react-dom/index.fb.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * 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. - */ - -'use strict'; - -const ReactDOMFB = require('./src/client/ReactDOMFB'); - -// TODO: decide on the top-level export form. -// This is hacky but makes it work with both Rollup and Jest. -module.exports = ReactDOMFB.default || ReactDOMFB; diff --git a/packages/react-dom/index.js b/packages/react-dom/index.js index 2a016ba16e9..3714de11244 100644 --- a/packages/react-dom/index.js +++ b/packages/react-dom/index.js @@ -7,10 +7,4 @@ * @flow */ -'use strict'; - -const ReactDOM = require('./src/client/ReactDOM'); - -// TODO: decide on the top-level export form. -// This is hacky but makes it work with both Rollup and Jest. -module.exports = ReactDOM.default || ReactDOM; +export * from './src/client/ReactDOM'; diff --git a/packages/react-dom/index.modern.fb.js b/packages/react-dom/index.modern.fb.js new file mode 100644 index 00000000000..bcb213ad4ee --- /dev/null +++ b/packages/react-dom/index.modern.fb.js @@ -0,0 +1,22 @@ +/** + * 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 + */ + +export { + createPortal, + unstable_batchedUpdates, + flushSync, + __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, + version, + createRoot, + createBlockingRoot, + unstable_discreteUpdates, + unstable_flushDiscreteUpdates, + unstable_flushControlled, + unstable_scheduleHydration, +} from './src/client/ReactDOM'; diff --git a/packages/react-dom/index.stable.js b/packages/react-dom/index.stable.js new file mode 100644 index 00000000000..00d52806bab --- /dev/null +++ b/packages/react-dom/index.stable.js @@ -0,0 +1,24 @@ +/** + * 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 + */ + +export { + createPortal, + unstable_batchedUpdates, + flushSync, + __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, + version, + findDOMNode, + hydrate, + render, + unmountComponentAtNode, + unstable_renderSubtreeIntoContainer, + // Temporary alias since we already shipped React 16 RC with it. + // TODO: remove in React 17. + unstable_createPortal, +} from './src/client/ReactDOM'; diff --git a/packages/react-dom/src/client/ReactDOM.js b/packages/react-dom/src/client/ReactDOM.js index 791fc098293..83cf1b13d7b 100644 --- a/packages/react-dom/src/client/ReactDOM.js +++ b/packages/react-dom/src/client/ReactDOM.js @@ -35,7 +35,6 @@ import { attemptUserBlockingHydration, attemptContinuousHydration, attemptHydrationAtCurrentPriority, - act, } from 'react-reconciler/inline.dom'; import {createPortal as createPortalImpl} from 'shared/ReactPortal'; import {canUseDOM} from 'shared/ExecutionEnvironment'; @@ -56,14 +55,7 @@ import { } from 'legacy-events/EventPropagators'; import ReactVersion from 'shared/ReactVersion'; import invariant from 'shared/invariant'; -import { - exposeConcurrentModeAPIs, - disableLegacyReactDOMAPIs, - disableUnstableCreatePortal, - disableUnstableRenderSubtreeIntoContainer, - warnUnstableRenderSubtreeIntoContainer, - isTestEnvironment, -} from 'shared/ReactFeatureFlags'; +import {warnUnstableRenderSubtreeIntoContainer} from 'shared/ReactFeatureFlags'; import { getInstanceFromNode, @@ -129,95 +121,103 @@ function createPortal( return createPortalImpl(children, container, null, key); } -const ReactDOM: Object = { - createPortal, - - unstable_batchedUpdates: batchedUpdates, - - flushSync: flushSync, - - __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: { - // Keep in sync with ReactDOMUnstableNativeDependencies.js - // ReactTestUtils.js, and ReactTestUtilsAct.js. This is an array for better minification. - Events: [ - getInstanceFromNode, - getNodeFromInstance, - getFiberCurrentPropsFromNode, - injectEventPluginsByName, - eventNameDispatchConfigs, - accumulateTwoPhaseDispatches, - accumulateDirectDispatches, - enqueueStateRestore, - restoreStateIfNeeded, - dispatchEvent, - runEventsInBatch, - flushPassiveEffects, - IsThisRendererActing, - ], - }, - - version: ReactVersion, -}; - -if (!disableLegacyReactDOMAPIs) { - ReactDOM.findDOMNode = findDOMNode; - ReactDOM.hydrate = hydrate; - ReactDOM.render = render; - ReactDOM.unmountComponentAtNode = unmountComponentAtNode; +function scheduleHydration(target: Node) { + if (target) { + queueExplicitHydrationTarget(target); + } } -if (exposeConcurrentModeAPIs) { - ReactDOM.createRoot = createRoot; - ReactDOM.createBlockingRoot = createBlockingRoot; - - ReactDOM.unstable_discreteUpdates = discreteUpdates; - ReactDOM.unstable_flushDiscreteUpdates = flushDiscreteUpdates; - ReactDOM.unstable_flushControlled = flushControlled; - - ReactDOM.unstable_scheduleHydration = target => { - if (target) { - queueExplicitHydrationTarget(target); +function renderSubtreeIntoContainer( + parentComponent: React$Component, + element: React$Element, + containerNode: Container, + callback: ?Function, +) { + if (__DEV__) { + if ( + warnUnstableRenderSubtreeIntoContainer && + !didWarnAboutUnstableRenderSubtreeIntoContainer + ) { + didWarnAboutUnstableRenderSubtreeIntoContainer = true; + console.warn( + 'ReactDOM.unstable_renderSubtreeIntoContainer() is deprecated ' + + 'and will be removed in a future major release. Consider using ' + + 'React Portals instead.', + ); } - }; + } + return unstable_renderSubtreeIntoContainer( + parentComponent, + element, + containerNode, + callback, + ); } -if (!disableUnstableRenderSubtreeIntoContainer) { - ReactDOM.unstable_renderSubtreeIntoContainer = function(...args) { - if (__DEV__) { - if ( - warnUnstableRenderSubtreeIntoContainer && - !didWarnAboutUnstableRenderSubtreeIntoContainer - ) { - didWarnAboutUnstableRenderSubtreeIntoContainer = true; - console.warn( - 'ReactDOM.unstable_renderSubtreeIntoContainer() is deprecated ' + - 'and will be removed in a future major release. Consider using ' + - 'React Portals instead.', - ); - } +function unstable_createPortal( + children: ReactNodeList, + container: Container, + key: ?string = null, +) { + if (__DEV__) { + if (!didWarnAboutUnstableCreatePortal) { + didWarnAboutUnstableCreatePortal = true; + console.warn( + 'The ReactDOM.unstable_createPortal() alias has been deprecated, ' + + 'and will be removed in React 17+. Update your code to use ' + + 'ReactDOM.createPortal() instead. It has the exact same API, ' + + 'but without the "unstable_" prefix.', + ); } - return unstable_renderSubtreeIntoContainer(...args); - }; + } + return createPortal(children, container, key); } -if (!disableUnstableCreatePortal) { +const Internals = { + // Keep in sync with ReactDOMUnstableNativeDependencies.js + // ReactTestUtils.js, and ReactTestUtilsAct.js. This is an array for better minification. + Events: [ + getInstanceFromNode, + getNodeFromInstance, + getFiberCurrentPropsFromNode, + injectEventPluginsByName, + eventNameDispatchConfigs, + accumulateTwoPhaseDispatches, + accumulateDirectDispatches, + enqueueStateRestore, + restoreStateIfNeeded, + dispatchEvent, + runEventsInBatch, + flushPassiveEffects, + IsThisRendererActing, + ], +}; + +export { + createPortal, + batchedUpdates as unstable_batchedUpdates, + flushSync, + Internals as __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, + ReactVersion as version, + // Disabled behind disableLegacyReactDOMAPIs + findDOMNode, + hydrate, + render, + unmountComponentAtNode, + // exposeConcurrentModeAPIs + createRoot, + createBlockingRoot, + discreteUpdates as unstable_discreteUpdates, + flushDiscreteUpdates as unstable_flushDiscreteUpdates, + flushControlled as unstable_flushControlled, + scheduleHydration as unstable_scheduleHydration, + // Disabled behind disableUnstableRenderSubtreeIntoContainer + renderSubtreeIntoContainer as unstable_renderSubtreeIntoContainer, + // Disabled behind disableUnstableCreatePortal // Temporary alias since we already shipped React 16 RC with it. // TODO: remove in React 17. - ReactDOM.unstable_createPortal = function(...args) { - if (__DEV__) { - if (!didWarnAboutUnstableCreatePortal) { - didWarnAboutUnstableCreatePortal = true; - console.warn( - 'The ReactDOM.unstable_createPortal() alias has been deprecated, ' + - 'and will be removed in React 17+. Update your code to use ' + - 'ReactDOM.createPortal() instead. It has the exact same API, ' + - 'but without the "unstable_" prefix.', - ); - } - } - return createPortal(...args); - }; -} + unstable_createPortal, +}; const foundDevTools = injectIntoDevTools({ findFiberByHostInstance: getClosestInstanceFromNode, @@ -252,9 +252,3 @@ if (__DEV__) { } } } - -if (isTestEnvironment) { - ReactDOM.act = act; -} - -export default ReactDOM; diff --git a/packages/react-dom/src/client/ReactDOMFB.js b/packages/react-dom/src/client/ReactDOMFB.js deleted file mode 100644 index 02403919e77..00000000000 --- a/packages/react-dom/src/client/ReactDOMFB.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * 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 - */ - -import {addUserTimingListener} from 'shared/ReactFeatureFlags'; - -import ReactDOM from './ReactDOM'; -import {isEnabled} from '../events/ReactDOMEventListener'; -import {getClosestInstanceFromNode} from './ReactDOMComponentTree'; - -if (__EXPERIMENTAL__) { - // This is a modern WWW build. - // It should be the same as open source. Don't add new things here. -} else { - // For classic WWW builds, include a few internals that are already in use. - Object.assign( - (ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: any), - { - ReactBrowserEventEmitter: { - isEnabled, - }, - ReactDOMComponentTree: { - getClosestInstanceFromNode, - }, - // Perf experiment - addUserTimingListener, - }, - ); -} - -export default ReactDOM; diff --git a/packages/react-dom/testing.classic.fb.js b/packages/react-dom/testing.classic.fb.js new file mode 100644 index 00000000000..841f6a1d8f8 --- /dev/null +++ b/packages/react-dom/testing.classic.fb.js @@ -0,0 +1,11 @@ +/** + * 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 + */ + +export * from './index.classic.fb.js'; +export {act} from 'react-reconciler/inline.dom'; diff --git a/packages/react-dom/testing.experimental.js b/packages/react-dom/testing.experimental.js new file mode 100644 index 00000000000..0727208336c --- /dev/null +++ b/packages/react-dom/testing.experimental.js @@ -0,0 +1,11 @@ +/** + * 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 + */ + +export * from './index.experimental.js'; +export {act} from 'react-reconciler/inline.dom'; diff --git a/packages/react-dom/testing.js b/packages/react-dom/testing.js index 2a016ba16e9..6169f872726 100644 --- a/packages/react-dom/testing.js +++ b/packages/react-dom/testing.js @@ -7,10 +7,5 @@ * @flow */ -'use strict'; - -const ReactDOM = require('./src/client/ReactDOM'); - -// TODO: decide on the top-level export form. -// This is hacky but makes it work with both Rollup and Jest. -module.exports = ReactDOM.default || ReactDOM; +export * from './index.js'; +export {act} from 'react-reconciler/inline.dom'; diff --git a/packages/react-dom/testing.modern.fb.js b/packages/react-dom/testing.modern.fb.js new file mode 100644 index 00000000000..4eca948d499 --- /dev/null +++ b/packages/react-dom/testing.modern.fb.js @@ -0,0 +1,11 @@ +/** + * 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 + */ + +export * from './index.modern.fb.js'; +export {act} from 'react-reconciler/inline.dom'; diff --git a/packages/react-dom/testing.stable.js b/packages/react-dom/testing.stable.js new file mode 100644 index 00000000000..474972b70d8 --- /dev/null +++ b/packages/react-dom/testing.stable.js @@ -0,0 +1,11 @@ +/** + * 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 + */ + +export * from './index.stable.js'; +export {act} from 'react-reconciler/inline.dom'; From 90da1352af2bb60e7b469c41f865a4cb253b1ba7 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Sun, 23 Feb 2020 16:55:55 -0800 Subject: [PATCH 10/12] Fix ReactDOM Flow Types Now that ReactDOM is Flow type checked we need to fix up its types. --- packages/react-dom/src/client/ReactDOM.js | 3 ++- packages/react-dom/src/client/ReactDOMHostConfig.js | 4 ++-- packages/react-dom/src/client/ReactDOMLegacy.js | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/react-dom/src/client/ReactDOM.js b/packages/react-dom/src/client/ReactDOM.js index 83cf1b13d7b..340cba54773 100644 --- a/packages/react-dom/src/client/ReactDOM.js +++ b/packages/react-dom/src/client/ReactDOM.js @@ -112,12 +112,13 @@ function createPortal( children: ReactNodeList, container: Container, key: ?string = null, -) { +): React$Portal { invariant( isValidContainer(container), 'Target container is not a DOM element.', ); // TODO: pass ReactDOM portal implementation as third argument + // $FlowFixMe The Flow type is opaque but there's no way to actually create it. return createPortalImpl(children, container, null, key); } diff --git a/packages/react-dom/src/client/ReactDOMHostConfig.js b/packages/react-dom/src/client/ReactDOMHostConfig.js index f15805cee74..c61aa20c858 100644 --- a/packages/react-dom/src/client/ReactDOMHostConfig.js +++ b/packages/react-dom/src/client/ReactDOMHostConfig.js @@ -101,8 +101,8 @@ export type EventTargetChildElement = { ... }; export type Container = - | (Element & {_reactRootContainer: ?RootType, ...}) - | (Document & {_reactRootContainer: ?RootType, ...}); + | (Element & {_reactRootContainer?: RootType, ...}) + | (Document & {_reactRootContainer?: RootType, ...}); export type Instance = Element; export type TextInstance = Text; export type SuspenseInstance = Comment & {_reactRetry?: () => void, ...}; diff --git a/packages/react-dom/src/client/ReactDOMLegacy.js b/packages/react-dom/src/client/ReactDOMLegacy.js index d074ecf577e..97fbac29357 100644 --- a/packages/react-dom/src/client/ReactDOMLegacy.js +++ b/packages/react-dom/src/client/ReactDOMLegacy.js @@ -370,6 +370,7 @@ export function unmountComponentAtNode(container: Container) { // Unmount should not be batched. unbatchedUpdates(() => { legacyRenderSubtreeIntoContainer(null, null, container, false, () => { + // $FlowFixMe This should probably use `delete container._reactRootContainer` container._reactRootContainer = null; unmarkContainerAsRoot(container); }); From 76b7e97fd292cd78efc6f65e3855726d30395f5c Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Sun, 23 Feb 2020 17:28:44 -0800 Subject: [PATCH 11/12] Configure jest to use stable entry for ReactDOM in non-experimental --- scripts/jest/config.source-persistent.js | 3 +++ scripts/jest/config.source.js | 3 +++ 2 files changed, 6 insertions(+) diff --git a/scripts/jest/config.source-persistent.js b/scripts/jest/config.source-persistent.js index 388d906c2b2..63c95c5584b 100644 --- a/scripts/jest/config.source-persistent.js +++ b/scripts/jest/config.source-persistent.js @@ -17,6 +17,9 @@ const moduleNameMapper = {}; moduleNameMapper[ '^react$' ] = `/packages/react/index${preferredExtension}`; +moduleNameMapper[ + '^react-dom$' +] = `/packages/react-dom/index${preferredExtension}`; module.exports = Object.assign({}, baseConfig, { // Prefer the stable forks for tests. diff --git a/scripts/jest/config.source.js b/scripts/jest/config.source.js index 9b3179e0f84..18f44e3b721 100644 --- a/scripts/jest/config.source.js +++ b/scripts/jest/config.source.js @@ -17,6 +17,9 @@ const moduleNameMapper = {}; moduleNameMapper[ '^react$' ] = `/packages/react/index${preferredExtension}`; +moduleNameMapper[ + '^react-dom$' +] = `/packages/react-dom/index${preferredExtension}`; module.exports = Object.assign({}, baseConfig, { // Prefer the stable forks for tests. From cb4ff7bce79e48454b02e47fb173a657ba116466 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Sun, 23 Feb 2020 18:40:40 -0800 Subject: [PATCH 12/12] Remove additional FeatureFlags that are no longer needed These are only flagging the exports and no implementation details so we can control them fully through the export overrides. --- .../src/__tests__/ReactDOMFiber-test.js | 4 +--- .../__tests__/renderSubtreeIntoContainer-test.js | 2 +- packages/shared/ReactFeatureFlags.js | 16 ---------------- .../shared/forks/ReactFeatureFlags.native-fb.js | 5 ----- .../shared/forks/ReactFeatureFlags.native-oss.js | 5 ----- .../shared/forks/ReactFeatureFlags.persistent.js | 5 ----- .../forks/ReactFeatureFlags.test-renderer.js | 5 ----- .../forks/ReactFeatureFlags.test-renderer.www.js | 5 ----- .../shared/forks/ReactFeatureFlags.testing.js | 5 ----- .../forks/ReactFeatureFlags.testing.www.js | 5 ----- packages/shared/forks/ReactFeatureFlags.www.js | 10 ---------- 11 files changed, 2 insertions(+), 65 deletions(-) diff --git a/packages/react-dom/src/__tests__/ReactDOMFiber-test.js b/packages/react-dom/src/__tests__/ReactDOMFiber-test.js index efc605a9edb..ef872dfeb47 100644 --- a/packages/react-dom/src/__tests__/ReactDOMFiber-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMFiber-test.js @@ -13,8 +13,6 @@ const React = require('react'); const ReactDOM = require('react-dom'); const PropTypes = require('prop-types'); -const ReactFeatureFlags = require('shared/ReactFeatureFlags'); - describe('ReactDOMFiber', () => { let container; @@ -249,7 +247,7 @@ describe('ReactDOMFiber', () => { }); // TODO: remove in React 17 - if (!ReactFeatureFlags.disableUnstableCreatePortal) { + if (!__EXPERIMENTAL__) { it('should support unstable_createPortal alias', () => { const portalContainer = document.createElement('div'); diff --git a/packages/react-dom/src/__tests__/renderSubtreeIntoContainer-test.js b/packages/react-dom/src/__tests__/renderSubtreeIntoContainer-test.js index 2a540f9929d..678f96de9f0 100644 --- a/packages/react-dom/src/__tests__/renderSubtreeIntoContainer-test.js +++ b/packages/react-dom/src/__tests__/renderSubtreeIntoContainer-test.js @@ -19,7 +19,7 @@ const renderSubtreeIntoContainer = require('react-dom') const ReactFeatureFlags = require('shared/ReactFeatureFlags'); // Once this flag is always true, we should delete this test file -if (ReactFeatureFlags.disableUnstableRenderSubtreeIntoContainer) { +if (__EXPERIMENTAL__) { describe('renderSubtreeIntoContainer', () => { it('empty test', () => { // Empty test to prevent "Your test suite must contain at least one test." error. diff --git a/packages/shared/ReactFeatureFlags.js b/packages/shared/ReactFeatureFlags.js index 4ecf7b69d16..784accd974c 100644 --- a/packages/shared/ReactFeatureFlags.js +++ b/packages/shared/ReactFeatureFlags.js @@ -44,10 +44,6 @@ export function addUserTimingListener() { // Disable javascript: URL strings in href for XSS protection. export const disableJavaScriptURLs = false; -// These APIs will no longer be "unstable" in the upcoming 16.7 release, -// Control this behavior with a flag to support 16.6 minor releases in the meanwhile. -export const exposeConcurrentModeAPIs = __EXPERIMENTAL__; - // Warns when a combination of updates on a dom can cause a style declaration // that clashes with a previous one https://github.com/facebook/react/pull/14181 export const warnAboutShorthandPropertyCollision = true; @@ -107,10 +103,6 @@ export const runAllPassiveEffectDestroysBeforeCreates = false; // WARNING This flag only has an affect if used with runAllPassiveEffectDestroysBeforeCreates. export const deferPassiveEffectCleanupDuringUnmount = false; -// Use this flag to generate "testing" builds, that include APIs like act() -// and extra warnings/errors -export const isTestEnvironment = false; - // Enables a warning when trying to spread a 'key' to an element; // a deprecated pattern we want to get rid of in the future export const warnAboutSpreadingKeyToJSX = false; @@ -127,22 +119,14 @@ export const warnAboutStringRefs = false; export const disableLegacyContext = false; -// Disables hydrate, render, findDOMNode, unmountComponentAtNode -export const disableLegacyReactDOMAPIs = false; - // Disables children for