Skip to content

Commit c40b0ae

Browse files
committed
[Fiber] Disable comments as containers in OSS
3 years ago we partially disabled comment nodes as valid containers. Some unflagged support was left in due to legacy APIs like `unmountComponentAtNode` and `unstable_renderSubtreeIntoContainer` but these were since removed in React 19. This update flags the remaining uses of comments as containers.
1 parent 5832fe9 commit c40b0ae

File tree

5 files changed

+75
-87
lines changed

5 files changed

+75
-87
lines changed

packages/react-dom-bindings/src/client/ReactDOMContainer.js

-13
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,3 @@ export function isValidContainer(node: any): boolean {
2727
(node: any).nodeValue === ' react-mount-point-unstable '))
2828
);
2929
}
30-
31-
// TODO: Remove this function which also includes comment nodes.
32-
// We only use it in places that are currently more relaxed.
33-
export function isValidContainerLegacy(node: any): boolean {
34-
return !!(
35-
node &&
36-
(node.nodeType === ELEMENT_NODE ||
37-
node.nodeType === DOCUMENT_NODE ||
38-
node.nodeType === DOCUMENT_FRAGMENT_NODE ||
39-
(node.nodeType === COMMENT_NODE &&
40-
(node: any).nodeValue === ' react-mount-point-unstable '))
41-
);
42-
}

packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js

+56-65
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ import {
9393
enableTrustedTypesIntegration,
9494
disableLegacyMode,
9595
enableMoveBefore,
96+
disableCommentsAsDOMContainers,
9697
} from 'shared/ReactFeatureFlags';
9798
import {
9899
HostComponent,
@@ -257,7 +258,7 @@ export function getRootHostContext(
257258
}
258259
default: {
259260
const container: any =
260-
nodeType === COMMENT_NODE
261+
!disableCommentsAsDOMContainers && nodeType === COMMENT_NODE
261262
? rootContainerInstance.parentNode
262263
: rootContainerInstance;
263264
type = container.tagName;
@@ -801,29 +802,25 @@ export function appendChildToContainer(
801802
container: Container,
802803
child: Instance | TextInstance,
803804
): void {
804-
let parentNode: Document | Element;
805-
switch (container.nodeType) {
806-
case COMMENT_NODE: {
807-
parentNode = (container.parentNode: any);
808-
if (supportsMoveBefore) {
809-
// $FlowFixMe[prop-missing]: We've checked this with supportsMoveBefore.
810-
parentNode.moveBefore(child, container);
811-
} else {
812-
parentNode.insertBefore(child, container);
813-
}
814-
return;
815-
}
816-
case DOCUMENT_NODE: {
817-
parentNode = (container: any).body;
818-
break;
819-
}
820-
default: {
821-
if (container.nodeName === 'HTML') {
822-
parentNode = (container.ownerDocument.body: any);
823-
} else {
824-
parentNode = (container: any);
825-
}
805+
let parentNode: DocumentFragment | Element;
806+
if (container.nodeType === DOCUMENT_NODE) {
807+
parentNode = (container: any).body;
808+
} else if (
809+
!disableCommentsAsDOMContainers &&
810+
container.nodeType === COMMENT_NODE
811+
) {
812+
parentNode = (container.parentNode: any);
813+
if (supportsMoveBefore) {
814+
// $FlowFixMe[prop-missing]: We've checked this with supportsMoveBefore.
815+
parentNode.moveBefore(child, container);
816+
} else {
817+
parentNode.insertBefore(child, container);
826818
}
819+
return;
820+
} else if (container.nodeName === 'HTML') {
821+
parentNode = (container.ownerDocument.body: any);
822+
} else {
823+
parentNode = (container: any);
827824
}
828825
if (supportsMoveBefore) {
829826
// $FlowFixMe[prop-missing]: We've checked this with supportsMoveBefore.
@@ -868,24 +865,18 @@ export function insertInContainerBefore(
868865
child: Instance | TextInstance,
869866
beforeChild: Instance | TextInstance | SuspenseInstance,
870867
): void {
871-
let parentNode: Document | Element;
872-
switch (container.nodeType) {
873-
case COMMENT_NODE: {
874-
parentNode = (container.parentNode: any);
875-
break;
876-
}
877-
case DOCUMENT_NODE: {
878-
const ownerDocument: Document = (container: any);
879-
parentNode = (ownerDocument.body: any);
880-
break;
881-
}
882-
default: {
883-
if (container.nodeName === 'HTML') {
884-
parentNode = (container.ownerDocument.body: any);
885-
} else {
886-
parentNode = (container: any);
887-
}
888-
}
868+
let parentNode: DocumentFragment | Element;
869+
if (container.nodeType === DOCUMENT_NODE) {
870+
parentNode = (container: any).body;
871+
} else if (
872+
!disableCommentsAsDOMContainers &&
873+
container.nodeType === COMMENT_NODE
874+
) {
875+
parentNode = (container.parentNode: any);
876+
} else if (container.nodeName === 'HTML') {
877+
parentNode = (container.ownerDocument.body: any);
878+
} else {
879+
parentNode = (container: any);
889880
}
890881
if (supportsMoveBefore) {
891882
// $FlowFixMe[prop-missing]: We've checked this with supportsMoveBefore.
@@ -942,20 +933,18 @@ export function removeChildFromContainer(
942933
container: Container,
943934
child: Instance | TextInstance | SuspenseInstance,
944935
): void {
945-
let parentNode: Document | Element;
946-
switch (container.nodeType) {
947-
case COMMENT_NODE:
948-
parentNode = (container.parentNode: any);
949-
break;
950-
case DOCUMENT_NODE:
951-
parentNode = (container: any).body;
952-
break;
953-
default:
954-
if (container.nodeName === 'HTML') {
955-
parentNode = (container.ownerDocument.body: any);
956-
} else {
957-
parentNode = (container: any);
958-
}
936+
let parentNode: DocumentFragment | Element;
937+
if (container.nodeType === DOCUMENT_NODE) {
938+
parentNode = (container: any).body;
939+
} else if (
940+
!disableCommentsAsDOMContainers &&
941+
container.nodeType === COMMENT_NODE
942+
) {
943+
parentNode = (container.parentNode: any);
944+
} else if (container.nodeName === 'HTML') {
945+
parentNode = (container.ownerDocument.body: any);
946+
} else {
947+
parentNode = (container: any);
959948
}
960949
parentNode.removeChild(child);
961950
}
@@ -1021,18 +1010,20 @@ export function clearSuspenseBoundaryFromContainer(
10211010
container: Container,
10221011
suspenseInstance: SuspenseInstance,
10231012
): void {
1024-
if (container.nodeType === COMMENT_NODE) {
1025-
clearSuspenseBoundary((container.parentNode: any), suspenseInstance);
1026-
} else if (container.nodeType === DOCUMENT_NODE) {
1027-
clearSuspenseBoundary((container: any).body, suspenseInstance);
1013+
let parentNode: DocumentFragment | Element;
1014+
if (container.nodeType === DOCUMENT_NODE) {
1015+
parentNode = (container: any).body;
1016+
} else if (
1017+
!disableCommentsAsDOMContainers &&
1018+
container.nodeType === COMMENT_NODE
1019+
) {
1020+
parentNode = (container.parentNode: any);
10281021
} else if (container.nodeName === 'HTML') {
1029-
clearSuspenseBoundary(
1030-
(container.ownerDocument.body: any),
1031-
suspenseInstance,
1032-
);
1022+
parentNode = (container.ownerDocument.body: any);
10331023
} else {
1034-
clearSuspenseBoundary((container: any), suspenseInstance);
1024+
parentNode = (container: any);
10351025
}
1026+
clearSuspenseBoundary(parentNode, suspenseInstance);
10361027
// Retry if any event replaying was blocked on this.
10371028
retryIfBlockedOn(container);
10381029
}
@@ -1973,7 +1964,7 @@ export function getNextHydratableSiblingAfterSingleton(
19731964
export function describeHydratableInstanceForDevWarnings(
19741965
instance: HydratableInstance,
19751966
): string | {type: string, props: $ReadOnly<Props>} {
1976-
// Reverse engineer a pseudo react-element from hydratable instnace
1967+
// Reverse engineer a pseudo react-element from hydratable instance
19771968
if (instance.nodeType === ELEMENT_NODE) {
19781969
// Reverse engineer a set of props that can print for dev warnings
19791970
return {

packages/react-dom-bindings/src/events/DOMPluginEventSystem.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import {
5353
enableCreateEventHandleAPI,
5454
enableScopeAPI,
5555
enableOwnerStacks,
56+
disableCommentsAsDOMContainers,
5657
} from 'shared/ReactFeatureFlags';
5758
import {createEventListenerWrapperWithPriority} from './ReactDOMEventListener';
5859
import {
@@ -558,7 +559,8 @@ function isMatchingRootContainer(
558559
): boolean {
559560
return (
560561
grandContainer === targetContainer ||
561-
(grandContainer.nodeType === COMMENT_NODE &&
562+
(!disableCommentsAsDOMContainers &&
563+
grandContainer.nodeType === COMMENT_NODE &&
562564
grandContainer.parentNode === targetContainer)
563565
);
564566
}

packages/react-dom/src/client/ReactDOMRoot.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import type {
1616
import {isValidContainer} from 'react-dom-bindings/src/client/ReactDOMContainer';
1717
import {queueExplicitHydrationTarget} from 'react-dom-bindings/src/events/ReactDOMEventReplaying';
1818
import {REACT_ELEMENT_TYPE} from 'shared/ReactSymbols';
19+
import {disableCommentsAsDOMContainers} from 'shared/ReactFeatureFlags';
1920

2021
export type RootType = {
2122
render(children: ReactNodeList): void,
@@ -236,7 +237,7 @@ export function createRoot(
236237
markContainerAsRoot(root.current, container);
237238

238239
const rootContainerElement: Document | Element | DocumentFragment =
239-
container.nodeType === COMMENT_NODE
240+
!disableCommentsAsDOMContainers && container.nodeType === COMMENT_NODE
240241
? (container.parentNode: any)
241242
: container;
242243
listenToAllSupportedEvents(rootContainerElement);

packages/react-dom/src/client/ReactDOMRootFB.js

+14-7
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ import {
2727
hydrateRoot as hydrateRootImpl,
2828
} from './ReactDOMRoot';
2929

30-
import {disableLegacyMode} from 'shared/ReactFeatureFlags';
30+
import {
31+
disableLegacyMode,
32+
disableCommentsAsDOMContainers,
33+
} from 'shared/ReactFeatureFlags';
3134
import {clearContainer} from 'react-dom-bindings/src/client/ReactFiberConfigDOM';
3235
import {
3336
getInstanceFromNode,
@@ -36,7 +39,7 @@ import {
3639
unmarkContainerAsRoot,
3740
} from 'react-dom-bindings/src/client/ReactDOMComponentTree';
3841
import {listenToAllSupportedEvents} from 'react-dom-bindings/src/events/DOMPluginEventSystem';
39-
import {isValidContainerLegacy} from 'react-dom-bindings/src/client/ReactDOMContainer';
42+
import {isValidContainer} from 'react-dom-bindings/src/client/ReactDOMContainer';
4043
import {
4144
DOCUMENT_NODE,
4245
ELEMENT_NODE,
@@ -244,7 +247,9 @@ function legacyCreateRootFromDOMContainer(
244247
markContainerAsRoot(root.current, container);
245248

246249
const rootContainerElement =
247-
container.nodeType === COMMENT_NODE ? container.parentNode : container;
250+
!disableCommentsAsDOMContainers && container.nodeType === COMMENT_NODE
251+
? container.parentNode
252+
: container;
248253
// $FlowFixMe[incompatible-call]
249254
listenToAllSupportedEvents(rootContainerElement);
250255

@@ -278,7 +283,9 @@ function legacyCreateRootFromDOMContainer(
278283
markContainerAsRoot(root.current, container);
279284

280285
const rootContainerElement =
281-
container.nodeType === COMMENT_NODE ? container.parentNode : container;
286+
!disableCommentsAsDOMContainers && container.nodeType === COMMENT_NODE
287+
? container.parentNode
288+
: container;
282289
// $FlowFixMe[incompatible-call]
283290
listenToAllSupportedEvents(rootContainerElement);
284291

@@ -394,7 +401,7 @@ export function render(
394401
);
395402
}
396403

397-
if (!isValidContainerLegacy(container)) {
404+
if (!isValidContainer(container)) {
398405
throw new Error('Target container is not a DOM element.');
399406
}
400407

@@ -428,7 +435,7 @@ export function unmountComponentAtNode(container: Container): boolean {
428435
}
429436
throw new Error('ReactDOM: Unsupported Legacy Mode API.');
430437
}
431-
if (!isValidContainerLegacy(container)) {
438+
if (!isValidContainer(container)) {
432439
throw new Error('Target container is not a DOM element.');
433440
}
434441

@@ -472,7 +479,7 @@ export function unmountComponentAtNode(container: Container): boolean {
472479
// Check if the container itself is a React root node.
473480
const isContainerReactRoot =
474481
container.nodeType === ELEMENT_NODE &&
475-
isValidContainerLegacy(container.parentNode) &&
482+
isValidContainer(container.parentNode) &&
476483
// $FlowFixMe[prop-missing]
477484
// $FlowFixMe[incompatible-use]
478485
!!container.parentNode._reactRootContainer;

0 commit comments

Comments
 (0)