diff --git a/.circleci/config.yml b/.circleci/config.yml
index ea8f6458f96bb..d5d0e4f8f488b 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -115,6 +115,106 @@ jobs:
RELEASE_CHANNEL: experimental
command: yarn test --maxWorkers=2
+ test_source_www:
+ docker: *docker
+ environment: *environment
+ steps:
+ - checkout
+ - *restore_yarn_cache
+ - *run_yarn
+ - run:
+ environment:
+ RELEASE_CHANNEL: stable
+ command: yarn test-www --maxWorkers=2
+
+ test_source_www_variant:
+ docker: *docker
+ environment: *environment
+ steps:
+ - checkout
+ - *restore_yarn_cache
+ - *run_yarn
+ - run:
+ environment:
+ RELEASE_CHANNEL: stable
+ command: yarn test-www-variant --maxWorkers=2
+
+ test_source_www_prod:
+ docker: *docker
+ environment: *environment
+ steps:
+ - checkout
+ - *restore_yarn_cache
+ - *run_yarn
+ - run:
+ environment:
+ NODE_ENV: production
+ RELEASE_CHANNEL: stable
+ command: yarn test-www --maxWorkers=2
+
+ test_source_www_variant_prod:
+ docker: *docker
+ environment: *environment
+ steps:
+ - checkout
+ - *restore_yarn_cache
+ - *run_yarn
+ - run:
+ environment:
+ NODE_ENV: production
+ RELEASE_CHANNEL: stable
+ command: yarn test-www-variant --maxWorkers=2
+
+ test_source_www_experimental:
+ docker: *docker
+ environment: *environment
+ steps:
+ - checkout
+ - *restore_yarn_cache
+ - *run_yarn
+ - run:
+ environment:
+ RELEASE_CHANNEL: experimental
+ command: yarn test-www --maxWorkers=2
+
+ test_source_www_variant_experimental:
+ docker: *docker
+ environment: *environment
+ steps:
+ - checkout
+ - *restore_yarn_cache
+ - *run_yarn
+ - run:
+ environment:
+ RELEASE_CHANNEL: experimental
+ command: yarn test-www-variant --maxWorkers=2
+
+ test_source_www_prod_experimental:
+ docker: *docker
+ environment: *environment
+ steps:
+ - checkout
+ - *restore_yarn_cache
+ - *run_yarn
+ - run:
+ environment:
+ NODE_ENV: production
+ RELEASE_CHANNEL: experimental
+ command: yarn test-www --maxWorkers=2
+
+ test_source_www_variant_prod_experimental:
+ docker: *docker
+ environment: *environment
+ steps:
+ - checkout
+ - *restore_yarn_cache
+ - *run_yarn
+ - run:
+ environment:
+ NODE_ENV: production
+ RELEASE_CHANNEL: experimental
+ command: yarn test-www-variant --maxWorkers=2
+
test_source_persistent:
docker: *docker
environment: *environment
@@ -384,6 +484,18 @@ workflows:
- test_source_persistent:
requires:
- setup
+ - test_source_www:
+ requires:
+ - setup
+ - test_source_www_variant:
+ requires:
+ - setup
+ - test_source_www_prod:
+ requires:
+ - setup
+ - test_source_www_variant_prod:
+ requires:
+ - setup
- build:
requires:
- setup
@@ -415,6 +527,18 @@ workflows:
- test_source_prod_experimental:
requires:
- setup
+ - test_source_www_experimental:
+ requires:
+ - setup
+ - test_source_www_variant_experimental:
+ requires:
+ - setup
+ - test_source_www_prod_experimental:
+ requires:
+ - setup
+ - test_source_www_variant_prod_experimental:
+ requires:
+ - setup
- build_experimental:
requires:
- setup
diff --git a/.eslintrc.js b/.eslintrc.js
index b10d30525c198..112b17120f065 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -11,10 +11,7 @@ const OFF = 0;
const ERROR = 2;
module.exports = {
- extends: [
- 'fbjs',
- 'prettier'
- ],
+ extends: ['fbjs', 'prettier'],
// Stop ESLint from looking for a configuration file in parent folders
root: true,
@@ -147,7 +144,7 @@ module.exports = {
'scripts/**/*.js',
'packages/*/npm/**/*.js',
'packages/dom-event-testing-library/**/*.js',
- 'packages/react-devtools*/**/*.js'
+ 'packages/react-devtools*/**/*.js',
],
rules: {
'react-internal/no-production-logging': OFF,
@@ -171,6 +168,7 @@ module.exports = {
__PROFILE__: true,
__UMD__: true,
__EXPERIMENTAL__: true,
+ __VARIANT__: true,
trustedTypes: true,
},
};
diff --git a/package.json b/package.json
index 42fa148eb0714..bc48ac2fc5719 100644
--- a/package.json
+++ b/package.json
@@ -108,6 +108,8 @@
"postinstall": "node node_modules/fbjs-scripts/node/check-dev-engines.js package.json && node ./scripts/flow/createFlowConfigs.js && node ./scripts/yarn/downloadReactIsForPrettyFormat.js",
"debug-test": "cross-env NODE_ENV=development node --inspect-brk node_modules/jest/bin/jest.js --config ./scripts/jest/config.source.js --runInBand",
"test": "cross-env NODE_ENV=development jest --config ./scripts/jest/config.source.js",
+ "test-www": "cross-env NODE_ENV=development jest --config ./scripts/jest/config.source-www.js",
+ "test-www-variant": "cross-env NODE_ENV=development VARIANT=true jest --config ./scripts/jest/config.source-www.js",
"test-persistent": "cross-env NODE_ENV=development jest --config ./scripts/jest/config.source-persistent.js",
"debug-test-persistent": "cross-env NODE_ENV=development node --inspect-brk node_modules/jest/bin/jest.js --config ./scripts/jest/config.source-persistent.js --runInBand",
"test-prod": "cross-env NODE_ENV=production jest --config ./scripts/jest/config.source.js",
diff --git a/packages/react-dom/src/__tests__/ReactServerRendering-test.js b/packages/react-dom/src/__tests__/ReactServerRendering-test.js
index bcefcdb652468..b920a025eae85 100644
--- a/packages/react-dom/src/__tests__/ReactServerRendering-test.js
+++ b/packages/react-dom/src/__tests__/ReactServerRendering-test.js
@@ -14,6 +14,8 @@ let React;
let ReactDOMServer;
let PropTypes;
let ReactCurrentDispatcher;
+let enableSuspenseServerRenderer = require('shared/ReactFeatureFlags')
+ .enableSuspenseServerRenderer;
function normalizeCodeLocInfo(str) {
return str && str.replace(/\(at .+?:\d+\)/g, '(at **)');
@@ -686,7 +688,7 @@ describe('ReactDOMServer', () => {
expect(markup).toBe('
');
});
- if (!__EXPERIMENTAL__) {
+ if (!enableSuspenseServerRenderer) {
it('throws for unsupported types on the server', () => {
expect(() => {
ReactDOMServer.renderToString();
diff --git a/packages/react-reconciler/src/ReactFiber.js b/packages/react-reconciler/src/ReactFiber.js
index 719544533b39b..4ff3aa45d27af 100644
--- a/packages/react-reconciler/src/ReactFiber.js
+++ b/packages/react-reconciler/src/ReactFiber.js
@@ -973,10 +973,10 @@ export function assignFiberPropertiesInDEV(
}
if (enableUserTimingAPI) {
target._debugID = source._debugID;
+ target._debugIsCurrentlyTiming = source._debugIsCurrentlyTiming;
}
target._debugSource = source._debugSource;
target._debugOwner = source._debugOwner;
- target._debugIsCurrentlyTiming = source._debugIsCurrentlyTiming;
target._debugNeedsRemount = source._debugNeedsRemount;
target._debugHookTypes = source._debugHookTypes;
return target;
diff --git a/packages/shared/forks/ReactFeatureFlags.www-dynamic.js b/packages/shared/forks/ReactFeatureFlags.www-dynamic.js
new file mode 100644
index 0000000000000..007577a1f4bc7
--- /dev/null
+++ b/packages/shared/forks/ReactFeatureFlags.www-dynamic.js
@@ -0,0 +1,32 @@
+/**
+ * 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 strict
+ */
+
+// In www, these flags are controlled by GKs. Because most GKs have some
+// population running in either mode, we should run our tests that way, too,
+//
+// Use __VARIANT__ to simulate a GK. The tests will be run twice: once
+// with the __VARIANT__ set to `true`, and once set to `false`.
+
+export const deferPassiveEffectCleanupDuringUnmount = __VARIANT__;
+export const runAllPassiveEffectDestroysBeforeCreates = __VARIANT__;
+export const warnAboutSpreadingKeyToJSX = __VARIANT__;
+
+// These are already tested in both modes using the build type dimension,
+// so we don't need to use __VARIANT__ to get extra coverage.
+export const debugRenderPhaseSideEffectsForStrictMode = __DEV__;
+export const replayFailedUnitOfWorkWithInvokeGuardedCallback = __DEV__;
+
+// TODO: These flags are hard-coded to the default values used in open source.
+// Update the tests so that they pass in either mode, then set these
+// to __VARIANT__.
+export const enableTrustedTypesIntegration = false;
+export const warnAboutShorthandPropertyCollision = true;
+export const disableInputAttributeSyncing = false;
+export const disableSchedulerTimeoutBasedOnReactExpirationTime = false;
+export const enableModernEventSystem = false;
diff --git a/packages/shared/forks/ReactFeatureFlags.www.js b/packages/shared/forks/ReactFeatureFlags.www.js
index 1f6840be998d7..e9919256bc12b 100644
--- a/packages/shared/forks/ReactFeatureFlags.www.js
+++ b/packages/shared/forks/ReactFeatureFlags.www.js
@@ -9,8 +9,11 @@
import typeof * as FeatureFlagsType from 'shared/ReactFeatureFlags';
import typeof * as ExportsType from './ReactFeatureFlags.www';
+import typeof * as DynamicFeatureFlags from './ReactFeatureFlags.www-dynamic';
// Re-export dynamic flags from the www version.
+const dynamicFeatureFlags: DynamicFeatureFlags = require('ReactFeatureFlags');
+
export const {
debugRenderPhaseSideEffectsForStrictMode,
deferPassiveEffectCleanupDuringUnmount,
@@ -20,8 +23,9 @@ export const {
warnAboutShorthandPropertyCollision,
disableSchedulerTimeoutBasedOnReactExpirationTime,
warnAboutSpreadingKeyToJSX,
+ replayFailedUnitOfWorkWithInvokeGuardedCallback,
enableModernEventSystem,
-} = require('ReactFeatureFlags');
+} = dynamicFeatureFlags;
// On WWW, __EXPERIMENTAL__ is used for a new modern build.
// It's not used anywhere in production yet.
@@ -39,7 +43,6 @@ export const enableProfilerCommitHooks = false;
export const enableSchedulerTracing = __PROFILE__;
export const enableSchedulerDebugging = true;
-export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
export const warnAboutDeprecatedLifecycles = true;
export const disableLegacyContext = __EXPERIMENTAL__;
export const warnAboutStringRefs = false;
diff --git a/scripts/flow/environment.js b/scripts/flow/environment.js
index 524cae905bc2e..270f1c4c9451d 100644
--- a/scripts/flow/environment.js
+++ b/scripts/flow/environment.js
@@ -12,6 +12,7 @@
declare var __PROFILE__: boolean;
declare var __UMD__: boolean;
declare var __EXPERIMENTAL__: boolean;
+declare var __VARIANT__: boolean;
declare var __REACT_DEVTOOLS_GLOBAL_HOOK__: any; /*?{
inject: ?((stuff: Object) => void)
diff --git a/scripts/jest/config.source-www.js b/scripts/jest/config.source-www.js
new file mode 100644
index 0000000000000..0d79c83bbebb0
--- /dev/null
+++ b/scripts/jest/config.source-www.js
@@ -0,0 +1,36 @@
+'use strict';
+
+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}`;
+moduleNameMapper[
+ '^react-dom$'
+] = `/packages/react-dom/index${preferredExtension}`;
+
+module.exports = Object.assign({}, baseConfig, {
+ // Prefer the stable forks for tests.
+ moduleNameMapper,
+ modulePathIgnorePatterns: [
+ ...baseConfig.modulePathIgnorePatterns,
+ 'packages/react-devtools-shared',
+ ],
+ setupFiles: [
+ ...baseConfig.setupFiles,
+ require.resolve('./setupHostConfigs.js'),
+ require.resolve('./setupTests.www.js'),
+ ],
+});
diff --git a/scripts/jest/setupEnvironment.js b/scripts/jest/setupEnvironment.js
index 7eef6432e73cf..456645cddaba9 100644
--- a/scripts/jest/setupEnvironment.js
+++ b/scripts/jest/setupEnvironment.js
@@ -17,6 +17,8 @@ global.__EXPERIMENTAL__ =
? RELEASE_CHANNEL === 'experimental'
: true;
+global.__VARIANT__ = !!process.env.VARIANT;
+
if (typeof window !== 'undefined') {
global.requestIdleCallback = function(callback) {
return setTimeout(() => {
diff --git a/scripts/jest/setupTests.www.js b/scripts/jest/setupTests.www.js
new file mode 100644
index 0000000000000..82cebc15bd247
--- /dev/null
+++ b/scripts/jest/setupTests.www.js
@@ -0,0 +1,23 @@
+'use strict';
+
+jest.mock('shared/ReactFeatureFlags', () => {
+ jest.mock(
+ 'ReactFeatureFlags',
+ () => jest.requireActual('shared/forks/ReactFeatureFlags.www-dynamic'),
+ {virtual: true}
+ );
+
+ const wwwFlags = jest.requireActual('shared/forks/ReactFeatureFlags.www');
+ const defaultFlags = jest.requireActual('shared/ReactFeatureFlags');
+
+ // TODO: Many tests were written before we started running them against the
+ // www configuration. Update those tests so that they work against the www
+ // configuration, too. Then remove these overrides.
+ wwwFlags.disableLegacyContext = defaultFlags.disableLegacyContext;
+ wwwFlags.warnAboutUnmockedScheduler = defaultFlags.warnAboutUnmockedScheduler;
+ wwwFlags.enableUserTimingAPI = defaultFlags.enableUserTimingAPI;
+ wwwFlags.disableJavaScriptURLs = defaultFlags.disableJavaScriptURLs;
+ wwwFlags.enableDeprecatedFlareAPI = defaultFlags.enableDeprecatedFlareAPI;
+
+ return wwwFlags;
+});
diff --git a/scripts/rollup/build.js b/scripts/rollup/build.js
index c3e7d8c7c73a8..cfc967249bf07 100644
--- a/scripts/rollup/build.js
+++ b/scripts/rollup/build.js
@@ -391,6 +391,7 @@ function getPlugins(
__UMD__: isUMDBundle ? 'true' : 'false',
'process.env.NODE_ENV': isProduction ? "'production'" : "'development'",
__EXPERIMENTAL__,
+ __VARIANT__: false,
}),
// The CommonJS plugin *only* exists to pull "art" into "react-art".
// I'm going to port "art" to ES modules to avoid this problem.