Add enableSuspenseServerRenderer feature flag (#13573)
Alex Taylor committed
Sep 5, 2018 at 15:04 UTC
34348a45b4b1de40d285ba7168e4d6770e620911
11 files changed
+97
-1
packages/react-dom/src/__tests__/ReactDOMServerPlaceholders-test.internal.js
new
+59
@@ -0,0 +1,59 @@
1
+/**
2
+ * Copyright (c) 2013-present, Facebook, Inc.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @emails react-core
8
+ */
9
+
10
+'use strict';
11
+
12
+const ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils');
13
+
14
+let React;
15
+let ReactDOM;
16
+let ReactDOMServer;
17
+let ReactFeatureFlags;
18
+
19
+function initModules() {
20
+ // Reset warning cache.
21
+ jest.resetModuleRegistry();
22
+
23
+ ReactFeatureFlags = require('shared/ReactFeatureFlags');
24
+ ReactFeatureFlags.enableSuspense = true;
25
+ ReactFeatureFlags.enableSuspenseServerRenderer = true;
26
+
27
+ React = require('react');
28
+ ReactDOM = require('react-dom');
29
+ ReactDOMServer = require('react-dom/server');
30
+
31
+ // Make them available to the helpers.
32
+ return {
33
+ ReactDOM,
34
+ ReactDOMServer,
35
+ };
36
+}
37
+
38
+const {resetModules, serverRender} = ReactDOMServerIntegrationUtils(
39
+ initModules,
40
+);
41
+
42
+describe('ReactDOMServerPlaceholders', () => {
43
+ beforeEach(() => {
44
+ resetModules();
45
+ });
46
+
47
+ it('should always render the fallback when a placeholder is encountered', async () => {
48
+ const Suspended = props => {
49
+ throw new Promise(() => {});
50
+ };
51
+ const e = await serverRender(
52
+ <React.Placeholder fallback={<div />}>
53
+ <Suspended />
54
+ </React.Placeholder>,
55
+ );
56
+
57
+ expect(e.tagName).toBe('DIV');
58
+ });
59
+});
packages/react-dom/src/server/ReactPartialRenderer.js
+27
-1
@@ -23,12 +23,17 @@ import warningWithoutStack from 'shared/warningWithoutStack';
23
import checkPropTypes from 'prop-types/checkPropTypes';
24
import describeComponentFrame from 'shared/describeComponentFrame';
25
import ReactSharedInternals from 'shared/ReactSharedInternals';
26
-import {warnAboutDeprecatedLifecycles} from 'shared/ReactFeatureFlags';
26
+import {
27
+ warnAboutDeprecatedLifecycles,
28
+ enableSuspenseServerRenderer,
29
+} from 'shared/ReactFeatureFlags';
30
+
31
import {
32
REACT_FORWARD_REF_TYPE,
33
REACT_FRAGMENT_TYPE,
34
REACT_STRICT_MODE_TYPE,
35
REACT_ASYNC_MODE_TYPE,
36
+ REACT_PLACEHOLDER_TYPE,
37
REACT_PORTAL_TYPE,
38
REACT_PROFILER_TYPE,
39
REACT_PROVIDER_TYPE,
@@ -911,6 +916,27 @@ class ReactDOMServerRenderer {
916
this.stack.push(frame);
917
return '';
918
}
919
+ case REACT_PLACEHOLDER_TYPE: {
920
+ if (enableSuspenseServerRenderer) {
921
+ const nextChildren = toArray(
922
+ // Always use the fallback when synchronously rendering to string.
923
+ ((nextChild: any): ReactElement).props.fallback,
924
+ );
925
+ const frame: Frame = {
926
+ type: null,
927
+ domNamespace: parentNamespace,
928
+ children: nextChildren,
929
+ childIndex: 0,
930
+ context: context,
931
+ footer: '',
932
+ };
933
+ if (__DEV__) {
934
+ ((frame: any): FrameDev).debugElementStack = [];
935
+ }
936
+ this.stack.push(frame);
937
+ return '';
938
+ }
939
+ }
940
// eslint-disable-next-line-no-fallthrough
941
default:
942
break;
packages/shared/ReactFeatureFlags.js
+3
@@ -42,6 +42,9 @@ export const enableProfilerTimer = __PROFILE__;
42
// Track which interactions trigger each commit.
43
export const enableSchedulerTracking = __PROFILE__;
44
45
+// Only used in www builds.
46
+export const enableSuspenseServerRenderer = false;
47
+
48
// Only used in www builds.
49
export function addUserTimingListener() {
50
invariant(false, 'Not implemented.');
packages/shared/forks/ReactFeatureFlags.native-fabric-fb.js
+1
@@ -22,6 +22,7 @@ export const warnAboutLegacyContextAPI = __DEV__;
22
export const replayFailedUnitOfWorkWithInvokeGuardedCallback = __DEV__;
23
export const enableProfilerTimer = __PROFILE__;
24
export const enableSchedulerTracking = __PROFILE__;
25
+export const enableSuspenseServerRenderer = false;
26
27
// Only used in www builds.
28
export function addUserTimingListener() {
packages/shared/forks/ReactFeatureFlags.native-fabric-oss.js
+1
@@ -22,6 +22,7 @@ export const warnAboutLegacyContextAPI = false;
22
export const replayFailedUnitOfWorkWithInvokeGuardedCallback = __DEV__;
23
export const enableProfilerTimer = __PROFILE__;
24
export const enableSchedulerTracking = __PROFILE__;
25
+export const enableSuspenseServerRenderer = false;
26
27
// Only used in www builds.
28
export function addUserTimingListener() {
packages/shared/forks/ReactFeatureFlags.native-fb.js
+1
@@ -27,6 +27,7 @@ export const enableUserTimingAPI = __DEV__;
27
export const warnAboutLegacyContextAPI = __DEV__;
28
export const enableProfilerTimer = __PROFILE__;
29
export const enableSchedulerTracking = __PROFILE__;
30
+export const enableSuspenseServerRenderer = false;
31
32
// Only used in www builds.
33
export function addUserTimingListener() {
packages/shared/forks/ReactFeatureFlags.native-oss.js
+1
@@ -22,6 +22,7 @@ export const warnAboutDeprecatedLifecycles = false;
22
export const warnAboutLegacyContextAPI = false;
23
export const enableProfilerTimer = __PROFILE__;
24
export const enableSchedulerTracking = __PROFILE__;
25
+export const enableSuspenseServerRenderer = false;
26
27
// Only used in www builds.
28
export function addUserTimingListener() {
packages/shared/forks/ReactFeatureFlags.persistent.js
+1
@@ -22,6 +22,7 @@ export const warnAboutLegacyContextAPI = false;
22
export const replayFailedUnitOfWorkWithInvokeGuardedCallback = __DEV__;
23
export const enableProfilerTimer = __PROFILE__;
24
export const enableSchedulerTracking = __PROFILE__;
25
+export const enableSuspenseServerRenderer = false;
26
27
// Only used in www builds.
28
export function addUserTimingListener() {
packages/shared/forks/ReactFeatureFlags.test-renderer.js
+1
@@ -22,6 +22,7 @@ export const warnAboutLegacyContextAPI = false;
22
export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
23
export const enableProfilerTimer = false;
24
export const enableSchedulerTracking = false;
25
+export const enableSuspenseServerRenderer = false;
26
27
// Only used in www builds.
28
export function addUserTimingListener() {
packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
+1
@@ -22,6 +22,7 @@ export const warnAboutLegacyContextAPI = false;
22
export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
23
export const enableProfilerTimer = false;
24
export const enableSchedulerTracking = false;
25
+export const enableSuspenseServerRenderer = false;
26
27
// Only used in www builds.
28
export function addUserTimingListener() {
packages/shared/forks/ReactFeatureFlags.www.js
+1
@@ -16,6 +16,7 @@ export const {
16
debugRenderPhaseSideEffects,
17
debugRenderPhaseSideEffectsForStrictMode,
18
enableGetDerivedStateFromCatch,
19
+ enableSuspenseServerRenderer,
20
replayFailedUnitOfWorkWithInvokeGuardedCallback,
21
warnAboutDeprecatedLifecycles,
22
} = require('ReactFeatureFlags');