Disallow comments as DOM containers for createRoot (#23321)
This is an old feature that we no longer support. `hydrateRoot` already throws if you pass a comment node; this change makes `createRoot` throw, too. Still enabled in the Facebook build until we migrate the callers.
Andrew Clark committed
Feb 17, 2022 at 16:44 UTC
54f785bc51800556dead12aaedf9594b2f15e836
11 files changed
+42
-3
packages/react-dom/src/__tests__/ReactDOMRoot-test.js
+18
@@ -402,4 +402,22 @@ describe('ReactDOMRoot', () => {
402
'already rendering.',
403
);
404
});
405
+
406
+ // @gate disableCommentsAsDOMContainers
407
+ it('errors if container is a comment node', () => {
408
+ // This is an old feature used by www. Disabled in the open source build.
409
+ const div = document.createElement('div');
410
+ div.innerHTML = '<!-- react-mount-point-unstable -->';
411
+ const commentNode = div.childNodes[0];
412
+
413
+ expect(() => ReactDOM.createRoot(commentNode)).toThrow(
414
+ 'createRoot(...): Target container is not a DOM element.',
415
+ );
416
+ expect(() => ReactDOM.hydrateRoot(commentNode)).toThrow(
417
+ 'hydrateRoot(...): Target container is not a DOM element.',
418
+ );
419
+
420
+ // Still works in the legacy API
421
+ ReactDOM.render(<div />, commentNode);
422
+ });
423
});
packages/react-dom/src/client/ReactDOMRoot.js
+9
-3
@@ -68,7 +68,10 @@ import {
68
isAlreadyRendering,
69
} from 'react-reconciler/src/ReactFiberReconciler';
70
import {ConcurrentRoot} from 'react-reconciler/src/ReactRootTags';
71
-import {allowConcurrentByDefault} from 'shared/ReactFeatureFlags';
71
+import {
72
+ allowConcurrentByDefault,
73
+ disableCommentsAsDOMContainers,
74
+} from 'shared/ReactFeatureFlags';
75
76
/* global reportError */
77
const defaultOnRecoverableError =
@@ -153,7 +156,7 @@ export function createRoot(
156
container: Container,
157
options?: CreateRootOptions,
158
): RootType {
156
- if (!isValidContainerLegacy(container)) {
159
+ if (!isValidContainer(container)) {
160
throw new Error('createRoot(...): Target container is not a DOM element.');
161
}
162
@@ -293,7 +296,10 @@ export function isValidContainer(node: any): boolean {
296
node &&
297
(node.nodeType === ELEMENT_NODE ||
298
node.nodeType === DOCUMENT_NODE ||
296
- node.nodeType === DOCUMENT_FRAGMENT_NODE)
299
+ node.nodeType === DOCUMENT_FRAGMENT_NODE ||
300
+ (!disableCommentsAsDOMContainers &&
301
+ node.nodeType === COMMENT_NODE &&
302
+ (node: any).nodeValue === ' react-mount-point-unstable '))
303
);
304
}
305
packages/shared/ReactFeatureFlags.js
+4
@@ -68,6 +68,10 @@ export const enableSchedulerDebugging = false;
68
// Disable javascript: URL strings in href for XSS protection.
69
export const disableJavaScriptURLs = false;
70
71
+// Disable support for comment nodes as React DOM containers. Only supported
72
+// by www builds.
73
+export const disableCommentsAsDOMContainers = true;
74
+
75
// Experimental Scope support.
76
export const enableScopeAPI = false;
77
packages/shared/forks/ReactFeatureFlags.native-fb.js
+1
@@ -33,6 +33,7 @@ export const enableCache = false;
33
export const enableSchedulerDebugging = false;
34
export const debugRenderPhaseSideEffectsForStrictMode = true;
35
export const disableJavaScriptURLs = false;
36
+export const disableCommentsAsDOMContainers = true;
37
export const disableInputAttributeSyncing = false;
38
export const replayFailedUnitOfWorkWithInvokeGuardedCallback = __DEV__;
39
export const warnAboutDeprecatedLifecycles = true;
packages/shared/forks/ReactFeatureFlags.native-oss.js
+1
@@ -25,6 +25,7 @@ export const enableSelectiveHydration = false;
25
export const enableLazyElements = false;
26
export const enableCache = false;
27
export const disableJavaScriptURLs = false;
28
+export const disableCommentsAsDOMContainers = true;
29
export const disableInputAttributeSyncing = false;
30
export const enableSchedulerDebugging = false;
31
export const enableScopeAPI = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.js
+1
@@ -25,6 +25,7 @@ export const enableSelectiveHydration = false;
25
export const enableLazyElements = false;
26
export const enableCache = __EXPERIMENTAL__;
27
export const disableJavaScriptURLs = false;
28
+export const disableCommentsAsDOMContainers = true;
29
export const disableInputAttributeSyncing = false;
30
export const enableSchedulerDebugging = false;
31
export const enableScopeAPI = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.native.js
+1
@@ -25,6 +25,7 @@ export const enableSelectiveHydration = false;
25
export const enableLazyElements = false;
26
export const enableCache = false;
27
export const disableJavaScriptURLs = false;
28
+export const disableCommentsAsDOMContainers = true;
29
export const disableInputAttributeSyncing = false;
30
export const enableSchedulerDebugging = false;
31
export const enableScopeAPI = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
+1
@@ -26,6 +26,7 @@ export const enableLazyElements = false;
26
export const enableCache = true;
27
export const enableSchedulerDebugging = false;
28
export const disableJavaScriptURLs = false;
29
+export const disableCommentsAsDOMContainers = true;
30
export const disableInputAttributeSyncing = false;
31
export const enableScopeAPI = true;
32
export const enableCreateEventHandleAPI = false;
packages/shared/forks/ReactFeatureFlags.testing.js
+1
@@ -25,6 +25,7 @@ export const enableSelectiveHydration = false;
25
export const enableLazyElements = false;
26
export const enableCache = __EXPERIMENTAL__;
27
export const disableJavaScriptURLs = false;
28
+export const disableCommentsAsDOMContainers = true;
29
export const disableInputAttributeSyncing = false;
30
export const enableSchedulerDebugging = false;
31
export const enableScopeAPI = false;
packages/shared/forks/ReactFeatureFlags.testing.www.js
+1
@@ -25,6 +25,7 @@ export const enableSelectiveHydration = true;
25
export const enableLazyElements = false;
26
export const enableCache = true;
27
export const disableJavaScriptURLs = true;
28
+export const disableCommentsAsDOMContainers = true;
29
export const disableInputAttributeSyncing = false;
30
export const enableSchedulerDebugging = false;
31
export const enableScopeAPI = true;
packages/shared/forks/ReactFeatureFlags.www.js
+4
@@ -74,6 +74,10 @@ export const enableCache = true;
74
75
export const disableJavaScriptURLs = true;
76
77
+// TODO: www currently relies on this feature. It's disabled in open source.
78
+// Need to remove it.
79
+export const disableCommentsAsDOMContainers = false;
80
+
81
export const disableModulePatternComponents = true;
82
83
export const enableCreateEventHandleAPI = true;