@samitouri / QOS-React-2 / commits / 1a65d036ef

[cleanup] remove enableHostSingletons feature flag (#27583)

The flag is enabled everywhere, I think we can remove it now.

Jan Kassens committed Nov 16, 2023 at 17:42 UTC 1a65d036ef057b07a6b15f5604e399f91bc5ed73
28 files changed +82 -328
packages/react-dom-bindings/src/client/ReactDOMComponent.js
+3 -5
@@ -69,7 +69,6 @@ import {
69 enableCustomElementPropertySupport,
70 enableClientRenderFallbackOnTextMismatch,
71 enableFormActions,
72 - enableHostSingletons,
72 disableIEWorkarounds,
73 enableTrustedTypesIntegration,
74 enableFilterEmptyStringAttributesDOM,
@@ -394,8 +393,7 @@ function setProp(
393 // show within the <textarea> until it has been focused and blurred again.
394 // https://github.com/facebook/react/issues/6731#issuecomment-254874553
395 const canSetTextContent =
397 - (!enableHostSingletons || tag !== 'body') &&
398 - (tag !== 'textarea' || value !== '');
396 + tag !== 'body' && (tag !== 'textarea' || value !== '');
397 if (canSetTextContent) {
398 setTextContent(domElement, value);
399 }
@@ -403,7 +401,7 @@ function setProp(
401 if (__DEV__) {
402 validateTextNesting('' + value, tag);
403 }
406 - const canSetTextContent = !enableHostSingletons || tag !== 'body';
404 + const canSetTextContent = tag !== 'body';
405 if (canSetTextContent) {
406 setTextContent(domElement, '' + value);
407 }
@@ -2822,7 +2820,7 @@ export function diffHydratedProperties(
2820 // we can get away with it.
2821 // Host singletons get their children appended and don't use the text
2822 // content mechanism.
2825 - if (!enableHostSingletons || tag !== 'body') {
2823 + if (tag !== 'body') {
2824 domElement.textContent = (children: any);
2825 }
2826 }
packages/react-dom-bindings/src/client/ReactDOMComponentTree.js
+3 -7
@@ -34,11 +34,7 @@ import {
34
35 import {getParentSuspenseInstance} from './ReactFiberConfigDOM';
36
37 -import {
38 - enableScopeAPI,
39 - enableFloat,
40 - enableHostSingletons,
41 -} from 'shared/ReactFeatureFlags';
37 +import {enableScopeAPI, enableFloat} from 'shared/ReactFeatureFlags';
38
39 const randomKey = Math.random().toString(36).slice(2);
40 const internalInstanceKey = '__reactFiber$' + randomKey;
@@ -180,7 +176,7 @@ export function getInstanceFromNode(node: Node): Fiber | null {
176 tag === HostText ||
177 tag === SuspenseComponent ||
178 (enableFloat ? tag === HostHoistable : false) ||
183 - (enableHostSingletons ? tag === HostSingleton : false) ||
179 + tag === HostSingleton ||
180 tag === HostRoot
181 ) {
182 return inst;
@@ -200,7 +196,7 @@ export function getNodeFromInstance(inst: Fiber): Instance | TextInstance {
196 if (
197 tag === HostComponent ||
198 (enableFloat ? tag === HostHoistable : false) ||
203 - (enableHostSingletons ? tag === HostSingleton : false) ||
199 + tag === HostSingleton ||
200 tag === HostText
201 ) {
202 // In Fiber this, is just the state node right now. We assume it will be
packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
+18 -35
@@ -92,7 +92,6 @@ import {
92 enableCreateEventHandleAPI,
93 enableScopeAPI,
94 enableFloat,
95 - enableHostSingletons,
95 enableTrustedTypesIntegration,
96 enableFormActions,
97 enableAsyncActions,
@@ -939,32 +938,18 @@ export function unhideTextInstance(
938 }
939
940 export function clearContainer(container: Container): void {
942 - if (enableHostSingletons) {
943 - const nodeType = container.nodeType;
944 - if (nodeType === DOCUMENT_NODE) {
945 - clearContainerSparingly(container);
946 - } else if (nodeType === ELEMENT_NODE) {
947 - switch (container.nodeName) {
948 - case 'HEAD':
949 - case 'HTML':
950 - case 'BODY':
951 - clearContainerSparingly(container);
952 - return;
953 - default: {
954 - container.textContent = '';
955 - }
956 - }
957 - }
958 - } else {
959 - if (container.nodeType === ELEMENT_NODE) {
960 - // We have refined the container to Element type
961 - const element: Element = (container: any);
962 - element.textContent = '';
963 - } else if (container.nodeType === DOCUMENT_NODE) {
964 - // We have refined the container to Document type
965 - const doc: Document = (container: any);
966 - if (doc.documentElement) {
967 - doc.removeChild(doc.documentElement);
941 + const nodeType = container.nodeType;
942 + if (nodeType === DOCUMENT_NODE) {
943 + clearContainerSparingly(container);
944 + } else if (nodeType === ELEMENT_NODE) {
945 + switch (container.nodeName) {
946 + case 'HEAD':
947 + case 'HTML':
948 + case 'BODY':
949 + clearContainerSparingly(container);
950 + return;
951 + default: {
952 + container.textContent = '';
953 }
954 }
955 }
@@ -1053,7 +1038,7 @@ export function canHydrateInstance(
1038 const element: Element = (instance: any);
1039 const anyProps = (props: any);
1040 if (element.nodeName.toLowerCase() !== type.toLowerCase()) {
1056 - if (!inRootOrSingleton || !enableHostSingletons) {
1041 + if (!inRootOrSingleton) {
1042 // Usually we error for mismatched tags.
1043 if (
1044 enableFormActions &&
@@ -1067,7 +1052,7 @@ export function canHydrateInstance(
1052 }
1053 }
1054 // In root or singleton parents we skip past mismatched instances.
1070 - } else if (!inRootOrSingleton || !enableHostSingletons) {
1055 + } else if (!inRootOrSingleton) {
1056 // Match
1057 if (
1058 enableFormActions &&
@@ -1212,7 +1197,7 @@ export function canHydrateTextInstance(
1197 ) {
1198 // If we have extra hidden inputs, we don't mismatch. This allows us to
1199 // embed extra form data in the original form.
1215 - } else if (!inRootOrSingleton || !enableHostSingletons) {
1200 + } else if (!inRootOrSingleton) {
1201 return null;
1202 }
1203 const nextInstance = getNextHydratableSibling(instance);
@@ -1230,7 +1215,7 @@ export function canHydrateSuspenseInstance(
1215 inRootOrSingleton: boolean,
1216 ): null | SuspenseInstance {
1217 while (instance.nodeType !== COMMENT_NODE) {
1233 - if (!inRootOrSingleton || !enableHostSingletons) {
1218 + if (!inRootOrSingleton) {
1219 return null;
1220 }
1221 const nextInstance = getNextHydratableSibling(instance);
@@ -1292,7 +1277,7 @@ export function canHydrateFormStateMarker(
1277 inRootOrSingleton: boolean,
1278 ): null | FormStateMarkerInstance {
1279 while (instance.nodeType !== COMMENT_NODE) {
1295 - if (!inRootOrSingleton || !enableHostSingletons) {
1280 + if (!inRootOrSingleton) {
1281 return null;
1282 }
1283 const nextInstance = getNextHydratableSibling(instance);
@@ -1501,9 +1486,7 @@ export function shouldDeleteUnhydratedTailInstances(
1486 parentType: string,
1487 ): boolean {
1488 return (
1504 - (enableHostSingletons ||
1505 - (parentType !== 'head' && parentType !== 'body')) &&
1506 - (!enableFormActions || (parentType !== 'form' && parentType !== 'button'))
1489 + !enableFormActions || (parentType !== 'form' && parentType !== 'button')
1490 );
1491 }
1492
packages/react-dom-bindings/src/events/DOMPluginEventSystem.js
+5 -10
@@ -53,7 +53,6 @@ import {
53 enableCreateEventHandleAPI,
54 enableScopeAPI,
55 enableFloat,
56 - enableHostSingletons,
56 enableFormActions,
57 } from 'shared/ReactFeatureFlags';
58 import {
@@ -637,7 +636,7 @@ export function dispatchEventForPluginEventSystem(
636 parentTag === HostComponent ||
637 parentTag === HostText ||
638 (enableFloat ? parentTag === HostHoistable : false) ||
640 - (enableHostSingletons ? parentTag === HostSingleton : false)
639 + parentTag === HostSingleton
640 ) {
641 node = ancestorInst = parentNode;
642 continue mainLoop;
@@ -695,7 +694,7 @@ export function accumulateSinglePhaseListeners(
694 if (
695 (tag === HostComponent ||
696 (enableFloat ? tag === HostHoistable : false) ||
698 - (enableHostSingletons ? tag === HostSingleton : false)) &&
697 + tag === HostSingleton) &&
698 stateNode !== null
699 ) {
700 lastHostComponent = stateNode;
@@ -809,7 +808,7 @@ export function accumulateTwoPhaseListeners(
808 if (
809 (tag === HostComponent ||
810 (enableFloat ? tag === HostHoistable : false) ||
812 - (enableHostSingletons ? tag === HostSingleton : false)) &&
811 + tag === HostSingleton) &&
812 stateNode !== null
813 ) {
814 const currentTarget = stateNode;
@@ -843,11 +842,7 @@ function getParent(inst: Fiber | null): Fiber | null {
842 // events to their parent. We could also go through parentNode on the
843 // host node but that wouldn't work for React Native and doesn't let us
844 // do the portal feature.
846 - } while (
847 - inst &&
848 - inst.tag !== HostComponent &&
849 - (!enableHostSingletons ? true : inst.tag !== HostSingleton)
850 - );
845 + } while (inst && inst.tag !== HostComponent && inst.tag !== HostSingleton);
846 if (inst) {
847 return inst;
848 }
@@ -916,7 +911,7 @@ function accumulateEnterLeaveListenersForEvent(
911 if (
912 (tag === HostComponent ||
913 (enableFloat ? tag === HostHoistable : false) ||
919 - (enableHostSingletons ? tag === HostSingleton : false)) &&
914 + tag === HostSingleton) &&
915 stateNode !== null
916 ) {
917 const currentTarget = stateNode;
packages/react-dom-bindings/src/events/plugins/EnterLeaveEventPlugin.js
+1 -4
@@ -24,7 +24,6 @@ import {
24 } from '../../client/ReactDOMComponentTree';
25 import {accumulateEnterLeaveTwoPhaseListeners} from '../DOMPluginEventSystem';
26
27 -import {enableHostSingletons} from 'shared/ReactFeatureFlags';
27 import {
28 HostComponent,
29 HostSingleton,
@@ -110,9 +109,7 @@ function extractEvents(
109 const tag = to.tag;
110 if (
111 to !== nearestMounted ||
113 - (tag !== HostComponent &&
114 - (!enableHostSingletons ? true : tag !== HostSingleton) &&
115 - tag !== HostText)
112 + (tag !== HostComponent && tag !== HostSingleton && tag !== HostText)
113 ) {
114 to = null;
115 }
packages/react-dom/src/__tests__/ReactDOMFloat-test.js
+3 -54
@@ -6202,7 +6202,7 @@ body {
6202 );
6203 });
6204
6205 - // @gate enableFloat && enableHostSingletons && enableClientRenderFallbackOnTextMismatch
6205 + // @gate enableFloat && enableClientRenderFallbackOnTextMismatch
6206 it('retains styles even when a new html, head, and/body mount', async () => {
6207 await act(() => {
6208 const {pipe} = renderToPipeableStream(
@@ -6254,58 +6254,7 @@ body {
6254 );
6255 });
6256
6257 - // @gate enableFloat && !enableHostSingletons
6258 - it('retains styles even when a new html, head, and/body mount - without HostSingleton', async () => {
6259 - await act(() => {
6260 - const {pipe} = renderToPipeableStream(
6261 - <html>
6262 - <head />
6263 - <body>
6264 - <link rel="stylesheet" href="foo" precedence="foo" />
6265 - <link rel="stylesheet" href="bar" precedence="bar" />
6266 - server
6267 - </body>
6268 - </html>,
6269 - );
6270 - pipe(writable);
6271 - });
6272 - const errors = [];
6273 - ReactDOMClient.hydrateRoot(
6274 - document,
6275 - <html>
6276 - <head>
6277 - <link rel="stylesheet" href="qux" precedence="qux" />
6278 - <link rel="stylesheet" href="foo" precedence="foo" />
6279 - </head>
6280 - <body>client</body>
6281 - </html>,
6282 - {
6283 - onRecoverableError(error) {
6284 - errors.push(error.message);
6285 - },
6286 - },
6287 - );
6288 - await expect(async () => {
6289 - await waitForAll([]);
6290 - }).toErrorDev(
6291 - [
6292 - 'Warning: Text content did not match. Server: "server" Client: "client"',
6293 - 'Warning: An error occurred during hydration. The server HTML was replaced with client content in <#document>.',
6294 - ],
6295 - {withoutStack: 1},
6296 - );
6297 - expect(getMeaningfulChildren(document)).toEqual(
6298 - <html>
6299 - <head>
6300 - <link rel="stylesheet" href="qux" data-precedence="qux" />
6301 - <link rel="stylesheet" href="foo" data-precedence="foo" />
6302 - </head>
6303 - <body>client</body>
6304 - </html>,
6305 - );
6306 - });
6307 -
6308 - // @gate enableFloat && enableHostSingletons
6257 + // @gate enableFloat
6258 it('retains styles in head through head remounts', async () => {
6259 const root = ReactDOMClient.createRoot(document);
6260 root.render(
@@ -8114,7 +8063,7 @@ background-color: green;
8063 ]);
8064 });
8065
8117 - // @gate enableFloat && enableHostSingletons && (enableClientRenderFallbackOnTextMismatch || !__DEV__)
8066 + // @gate enableFloat && (enableClientRenderFallbackOnTextMismatch || !__DEV__)
8067 it('can render a title before a singleton even if that singleton clears its contents', async () => {
8068 await act(() => {
8069 const {pipe} = renderToPipeableStream(
packages/react-dom/src/__tests__/ReactDOMRoot-test.js
+1 -1
@@ -375,7 +375,7 @@ describe('ReactDOMRoot', () => {
375 await waitForAll([]);
376 container.innerHTML = '';
377
378 - if (gate(flags => flags.enableFloat || flags.enableHostSingletons)) {
378 + if (gate(flags => flags.enableFloat)) {
379 // When either of these flags are on this validation is turned off so we
380 // expect there to be no warnings
381 root.render(<div>Hi</div>);
packages/react-dom/src/__tests__/ReactDOMSingletonComponents-test.js
+3 -15
@@ -123,7 +123,7 @@ describe('ReactDOM HostSingleton', () => {
123 : children;
124 }
125
126 - // @gate enableHostSingletons && enableFloat
126 + // @gate enableFloat
127 it('warns if you render the same singleton twice at the same time', async () => {
128 const root = ReactDOMClient.createRoot(document);
129 root.render(
@@ -208,16 +208,8 @@ describe('ReactDOM HostSingleton', () => {
208 );
209 });
210
211 - // @gate enableHostSingletons && enableFloat
211 + // @gate enableFloat
212 it('renders into html, head, and body persistently so the node identities never change and extraneous styles are retained', async () => {
213 - gate(flags => {
214 - if (flags.enableHostSingletons !== true) {
215 - // We throw here because when this test fails it ends up with sync work in a microtask
216 - // that throws after the expectTestToFail check asserts the failure. this causes even the
217 - // expected failure to fail. This just fails explicitly and early
218 - throw new Error('manually opting out of test');
219 - }
220 - });
213 // Server render some html that will get replaced with a client render
214 await actIntoEmptyDocument(() => {
215 const {pipe} = ReactDOMFizzServer.renderToPipeableStream(
@@ -601,7 +593,6 @@ describe('ReactDOM HostSingleton', () => {
593 });
594
595 // This test is not supported in this implementation. If we reintroduce insertion edge we should revisit
604 - // @gate enableHostSingletons
596 xit('is able to maintain insertions in head and body between tree-adjacent Nodes', async () => {
597 // Server render some html and hydrate on the client
598 await actIntoEmptyDocument(() => {
@@ -732,7 +723,6 @@ describe('ReactDOM HostSingleton', () => {
723 );
724 });
725
735 - // @gate enableHostSingletons
726 it('clears persistent head and body when html is the container', async () => {
727 await actIntoEmptyDocument(() => {
728 const {pipe} = ReactDOMFizzServer.renderToPipeableStream(
@@ -785,7 +775,6 @@ describe('ReactDOM HostSingleton', () => {
775 );
776 });
777
788 - // @gate enableHostSingletons
778 it('clears persistent head when it is the container', async () => {
779 await actIntoEmptyDocument(() => {
780 const {pipe} = ReactDOMFizzServer.renderToPipeableStream(
@@ -817,7 +806,7 @@ describe('ReactDOM HostSingleton', () => {
806 );
807 });
808
820 - // @gate enableHostSingletons && enableFloat
809 + // @gate enableFloat
810 it('clears persistent body when it is the container', async () => {
811 await actIntoEmptyDocument(() => {
812 const {pipe} = ReactDOMFizzServer.renderToPipeableStream(
@@ -974,7 +963,6 @@ describe('ReactDOM HostSingleton', () => {
963 );
964 });
965
977 - // @gate enableHostSingletons
966 it('allows for hydrating without a head', async () => {
967 await actIntoEmptyDocument(() => {
968 const {pipe} = ReactDOMFizzServer.renderToPipeableStream(
packages/react-dom/src/__tests__/ReactMount-test.js
+2 -11
@@ -149,17 +149,8 @@ describe('ReactMount', () => {
149 const iFrame = document.createElement('iframe');
150 document.body.appendChild(iFrame);
151
152 - if (gate(flags => flags.enableHostSingletons)) {
153 - // HostSingletons make the warning for document.body unecessary
154 - ReactDOM.render(<div />, iFrame.contentDocument.body);
155 - } else {
156 - expect(() =>
157 - ReactDOM.render(<div />, iFrame.contentDocument.body),
158 - ).toErrorDev(
159 - 'Rendering components directly into document.body is discouraged',
160 - {withoutStack: true},
161 - );
162 - }
152 + // HostSingletons make the warning for document.body unecessary
153 + ReactDOM.render(<div />, iFrame.contentDocument.body);
154 });
155
156 it('should account for escaping on a checksum mismatch', () => {
packages/react-dom/src/__tests__/ReactRenderDocument-test.js
-26
@@ -62,7 +62,6 @@ describe('rendering React components at document', () => {
62 expect(body === testDocument.body).toBe(true);
63 });
64
65 - // @gate enableHostSingletons
65 it('should be able to unmount component from document node, but leaves singleton nodes intact', () => {
66 class Root extends React.Component {
67 render() {
@@ -95,31 +94,6 @@ describe('rendering React components at document', () => {
94 expect(originalHead.firstChild).toEqual(null);
95 });
96
98 - // @gate !enableHostSingletons
99 - it('should be able to unmount component from document node', () => {
100 - class Root extends React.Component {
101 - render() {
102 - return (
103 - <html>
104 - <head>
105 - <title>Hello World</title>
106 - </head>
107 - <body>Hello world</body>
108 - </html>
109 - );
110 - }
111 - }
112 -
113 - const markup = ReactDOMServer.renderToString(<Root />);
114 - const testDocument = getTestDocument(markup);
115 - ReactDOM.hydrate(<Root />, testDocument);
116 - expect(testDocument.body.innerHTML).toBe('Hello world');
117 -
118 - // When we unmount everything is removed except the persistent nodes of html, head, and body
119 - ReactDOM.unmountComponentAtNode(testDocument);
120 - expect(testDocument.firstChild).toBe(null);
121 - });
122 -
97 it('should not be able to switch root constructors', () => {
98 class Component extends React.Component {
99 render() {
packages/react-dom/src/__tests__/validateDOMNesting-test.js
+18 -49
@@ -38,15 +38,7 @@ function expectWarnings(tags, warnings = [], withoutStack = 0) {
38 describe('validateDOMNesting', () => {
39 it('allows valid nestings', () => {
40 expectWarnings(['table', 'tbody', 'tr', 'td', 'b']);
41 - expectWarnings(
42 - ['body', 'datalist', 'option'],
43 - [
44 - gate(flags => !flags.enableHostSingletons)
45 - ? 'render(): Rendering components directly into document.body is discouraged'
46 - : null,
47 - ].filter(Boolean),
48 - 1,
49 - );
41 + expectWarnings(['body', 'datalist', 'option']);
42 expectWarnings(['div', 'a', 'object', 'a']);
43 expectWarnings(['div', 'p', 'button', 'p']);
44 expectWarnings(['p', 'svg', 'foreignObject', 'p']);
@@ -106,45 +98,22 @@ describe('validateDOMNesting', () => {
98 ' in html (at **)',
99 ],
100 );
109 - if (gate(flags => flags.enableHostSingletons)) {
110 - expectWarnings(
111 - ['body', 'body'],
112 - [
113 - 'validateDOMNesting(...): <body> cannot appear as a child of <body>.\n' +
114 - ' in body (at **)',
115 - ],
116 - );
117 - } else {
118 - expectWarnings(
119 - ['body', 'body'],
120 - [
121 - 'render(): Rendering components directly into document.body is discouraged',
122 - 'validateDOMNesting(...): <body> cannot appear as a child of <body>.\n' +
123 - ' in body (at **)',
124 - ],
125 - 1,
126 - );
127 - }
128 - if (gate(flags => flags.enableHostSingletons)) {
129 - expectWarnings(
130 - ['svg', 'foreignObject', 'body', 'p'],
131 - [
132 - 'validateDOMNesting(...): <body> cannot appear as a child of <foreignObject>.\n' +
133 - ' in body (at **)\n' +
134 - ' in foreignObject (at **)',
135 - 'Warning: You are mounting a new body component when a previous one has not first unmounted. It is an error to render more than one body component at a time and attributes and children of these components will likely fail in unpredictable ways. Please only render a single instance of <body> and if you need to mount a new one, ensure any previous ones have unmounted first.\n' +
136 - ' in body (at **)',
137 - ],
138 - );
139 - } else {
140 - expectWarnings(
141 - ['svg', 'foreignObject', 'body', 'p'],
142 - [
143 - 'validateDOMNesting(...): <body> cannot appear as a child of <foreignObject>.\n' +
144 - ' in body (at **)\n' +
145 - ' in foreignObject (at **)',
146 - ],
147 - );
148 - }
101 + expectWarnings(
102 + ['body', 'body'],
103 + [
104 + 'validateDOMNesting(...): <body> cannot appear as a child of <body>.\n' +
105 + ' in body (at **)',
106 + ],
107 + );
108 + expectWarnings(
109 + ['svg', 'foreignObject', 'body', 'p'],
110 + [
111 + 'validateDOMNesting(...): <body> cannot appear as a child of <foreignObject>.\n' +
112 + ' in body (at **)\n' +
113 + ' in foreignObject (at **)',
114 + 'Warning: You are mounting a new body component when a previous one has not first unmounted. It is an error to render more than one body component at a time and attributes and children of these components will likely fail in unpredictable ways. Please only render a single instance of <body> and if you need to mount a new one, ensure any previous ones have unmounted first.\n' +
115 + ' in body (at **)',
116 + ],
117 + );
118 });
119 });
packages/react-dom/src/client/ReactDOMLegacy.js
-16
@@ -43,7 +43,6 @@ import {LegacyRoot} from 'react-reconciler/src/ReactRootTags';
43 import getComponentNameFromType from 'shared/getComponentNameFromType';
44 import ReactSharedInternals from 'shared/ReactSharedInternals';
45 import {has as hasInstance} from 'shared/ReactInstanceMap';
46 -import {enableHostSingletons} from '../../../shared/ReactFeatureFlags';
46
47 const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
48
@@ -79,21 +78,6 @@ if (__DEV__) {
78 'and render the new components instead of calling ReactDOM.render.',
79 );
80 }
82 -
83 - if (
84 - !enableHostSingletons &&
85 - container.nodeType === ELEMENT_NODE &&
86 - ((container: any): Element).tagName &&
87 - ((container: any): Element).tagName.toUpperCase() === 'BODY'
88 - ) {
89 - console.error(
90 - 'render(): Rendering components directly into document.body is ' +
91 - 'discouraged, since its children are often manipulated by third-party ' +
92 - 'scripts and browser extensions. This may lead to subtle ' +
93 - 'reconciliation issues. Try rendering into a container element created ' +
94 - 'for your app.',
95 - );
96 - }
81 };
82 }
83
packages/react-dom/src/client/ReactDOMRoot.js
-36
@@ -18,7 +18,6 @@ import {queueExplicitHydrationTarget} from 'react-dom-bindings/src/events/ReactD
18 import {REACT_ELEMENT_TYPE} from 'shared/ReactSymbols';
19 import {
20 enableFloat,
21 - enableHostSingletons,
21 allowConcurrentByDefault,
22 disableCommentsAsDOMContainers,
23 enableAsyncActions,
@@ -78,7 +77,6 @@ import {
77 createContainer,
78 createHydrationContainer,
79 updateContainer,
81 - findHostInstanceWithNoPortals,
80 flushSync,
81 isAlreadyRendering,
82 } from 'react-reconciler/src/ReactFiberReconciler';
@@ -127,26 +125,6 @@ ReactDOMHydrationRoot.prototype.render = ReactDOMRoot.prototype.render =
125 'one argument.',
126 );
127 }
130 -
131 - const container = root.containerInfo;
132 -
133 - if (
134 - !enableFloat &&
135 - !enableHostSingletons &&
136 - container.nodeType !== COMMENT_NODE
137 - ) {
138 - const hostInstance = findHostInstanceWithNoPortals(root.current);
139 - if (hostInstance) {
140 - if (hostInstance.parentNode !== container) {
141 - console.error(
142 - 'render(...): It looks like the React-rendered content of the ' +
143 - 'root container was removed without using React. This is not ' +
144 - 'supported and will cause errors. Instead, call ' +
145 - "root.unmount() to empty a root's container.",
146 - );
147 - }
148 - }
149 - }
128 }
129 updateContainer(children, root, null, null);
130 };
@@ -381,20 +359,6 @@ export function isValidContainerLegacy(node: any): boolean {
359
360 function warnIfReactDOMContainerInDEV(container: any) {
361 if (__DEV__) {
384 - if (
385 - !enableHostSingletons &&
386 - container.nodeType === ELEMENT_NODE &&
387 - ((container: any): Element).tagName &&
388 - ((container: any): Element).tagName.toUpperCase() === 'BODY'
389 - ) {
390 - console.error(
391 - 'createRoot(): Creating roots directly with document.body is ' +
392 - 'discouraged, since its children are often manipulated by third-party ' +
393 - 'scripts and browser extensions. This may lead to subtle ' +
394 - 'reconciliation issues. Try using a container element created ' +
395 - 'for your app.',
396 - );
397 - }
362 if (isContainerMarkedAsRoot(container)) {
363 if (container._reactRootContainer) {
364 console.error(
packages/react-dom/src/test-utils/ReactTestUtils.js
+3 -7
@@ -25,7 +25,7 @@ import {
25 rethrowCaughtError,
26 invokeGuardedCallbackAndCatchFirstError,
27 } from 'shared/ReactErrorUtils';
28 -import {enableFloat, enableHostSingletons} from 'shared/ReactFeatureFlags';
28 +import {enableFloat} from 'shared/ReactFeatureFlags';
29 import assign from 'shared/assign';
30 import isArray from 'shared/isArray';
31
@@ -66,7 +66,7 @@ function findAllInRenderedFiberTreeInternal(fiber, test) {
66 node.tag === ClassComponent ||
67 node.tag === FunctionComponent ||
68 (enableFloat ? node.tag === HostHoistable : false) ||
69 - (enableHostSingletons ? node.tag === HostSingleton : false)
69 + node.tag === HostSingleton
70 ) {
71 const publicInst = node.stateNode;
72 if (test(publicInst)) {
@@ -419,11 +419,7 @@ function getParent(inst) {
419 // events to their parent. We could also go through parentNode on the
420 // host node but that wouldn't work for React Native and doesn't let us
421 // do the portal feature.
422 - } while (
423 - inst &&
424 - inst.tag !== HostComponent &&
425 - (!enableHostSingletons ? true : inst.tag !== HostSingleton)
426 - );
422 + } while (inst && inst.tag !== HostComponent && inst.tag !== HostSingleton);
423 if (inst) {
424 return inst;
425 }
packages/react-reconciler/src/ReactFiber.js
+2 -8
@@ -38,7 +38,6 @@ import {
38 enableTransitionTracing,
39 enableDebugTracing,
40 enableFloat,
41 - enableHostSingletons,
41 enableDO_NOT_USE_disableStrictPassiveEffect,
42 } from 'shared/ReactFeatureFlags';
43 import {NoFlags, Placement, StaticMask} from './ReactFiberFlags';
@@ -510,12 +509,7 @@ export function createFiberFromTypeAndProps(
509 }
510 }
511 } else if (typeof type === 'string') {
513 - if (
514 - enableFloat &&
515 - supportsResources &&
516 - enableHostSingletons &&
517 - supportsSingletons
518 - ) {
512 + if (enableFloat && supportsResources && supportsSingletons) {
513 const hostContext = getHostContext();
514 fiberTag = isHostHoistableType(type, pendingProps, hostContext)
515 ? HostHoistable
@@ -527,7 +521,7 @@ export function createFiberFromTypeAndProps(
521 fiberTag = isHostHoistableType(type, pendingProps, hostContext)
522 ? HostHoistable
523 : HostComponent;
530 - } else if (enableHostSingletons && supportsSingletons) {
524 + } else if (supportsSingletons) {
525 fiberTag = isHostSingletonType(type) ? HostSingleton : HostComponent;
526 } else {
527 fiberTag = HostComponent;
packages/react-reconciler/src/ReactFiberBeginWork.js
+1 -2
@@ -106,7 +106,6 @@ import {
106 enableLegacyHidden,
107 enableCPUSuspense,
108 enableFloat,
109 - enableHostSingletons,
109 enableFormActions,
110 enableAsyncActions,
111 enablePostpone,
@@ -4151,7 +4150,7 @@ function beginWork(
4150 }
4151 // Fall through
4152 case HostSingleton:
4154 - if (enableHostSingletons && supportsSingletons) {
4153 + if (supportsSingletons) {
4154 return updateHostSingleton(current, workInProgress, renderLanes);
4155 }
4156 // Fall through
packages/react-reconciler/src/ReactFiberCommitWork.js
+9 -16
@@ -53,7 +53,6 @@ import {
53 enableUseEffectEventHook,
54 enableFloat,
55 enableLegacyHidden,
56 - enableHostSingletons,
56 alwaysThrottleRetries,
57 } from 'shared/ReactFeatureFlags';
58 import {
@@ -1527,9 +1526,7 @@ function hideOrUnhideAllChildren(finishedWork: Fiber, isHidden: boolean) {
1526 (enableFloat && supportsResources
1527 ? node.tag === HostHoistable
1528 : false) ||
1530 - (enableHostSingletons && supportsSingletons
1531 - ? node.tag === HostSingleton
1532 - : false)
1529 + (supportsSingletons ? node.tag === HostSingleton : false)
1530 ) {
1531 if (hostSubtreeRoot === null) {
1532 hostSubtreeRoot = node;
@@ -1748,9 +1745,7 @@ function isHostParent(fiber: Fiber): boolean {
1745 fiber.tag === HostComponent ||
1746 fiber.tag === HostRoot ||
1747 (enableFloat && supportsResources ? fiber.tag === HostHoistable : false) ||
1751 - (enableHostSingletons && supportsSingletons
1752 - ? fiber.tag === HostSingleton
1753 - : false) ||
1748 + (supportsSingletons ? fiber.tag === HostSingleton : false) ||
1749 fiber.tag === HostPortal
1750 );
1751 }
@@ -1777,9 +1772,7 @@ function getHostSibling(fiber: Fiber): ?Instance {
1772 while (
1773 node.tag !== HostComponent &&
1774 node.tag !== HostText &&
1780 - (!(enableHostSingletons && supportsSingletons)
1781 - ? true
1782 - : node.tag !== HostSingleton) &&
1775 + (!supportsSingletons ? true : node.tag !== HostSingleton) &&
1776 node.tag !== DehydratedFragment
1777 ) {
1778 // If it is not host node and, we might have a host node inside it.
@@ -1810,7 +1803,7 @@ function commitPlacement(finishedWork: Fiber): void {
1803 return;
1804 }
1805
1813 - if (enableHostSingletons && supportsSingletons) {
1806 + if (supportsSingletons) {
1807 if (finishedWork.tag === HostSingleton) {
1808 // Singletons are already in the Host and don't need to be placed
1809 // Since they operate somewhat like Portals though their children will
@@ -1823,7 +1816,7 @@ function commitPlacement(finishedWork: Fiber): void {
1816
1817 switch (parentFiber.tag) {
1818 case HostSingleton: {
1826 - if (enableHostSingletons && supportsSingletons) {
1819 + if (supportsSingletons) {
1820 const parent: Instance = parentFiber.stateNode;
1821 const before = getHostSibling(finishedWork);
1822 // We only have the top Fiber that was inserted but we need to recurse down its
@@ -1879,7 +1872,7 @@ function insertOrAppendPlacementNodeIntoContainer(
1872 }
1873 } else if (
1874 tag === HostPortal ||
1882 - (enableHostSingletons && supportsSingletons ? tag === HostSingleton : false)
1875 + (supportsSingletons ? tag === HostSingleton : false)
1876 ) {
1877 // If the insertion itself is a portal, then we don't want to traverse
1878 // down its children. Instead, we'll get insertions from each child in
@@ -1914,7 +1907,7 @@ function insertOrAppendPlacementNode(
1907 }
1908 } else if (
1909 tag === HostPortal ||
1917 - (enableHostSingletons && supportsSingletons ? tag === HostSingleton : false)
1910 + (supportsSingletons ? tag === HostSingleton : false)
1911 ) {
1912 // If the insertion itself is a portal, then we don't want to traverse
1913 // down its children. Instead, we'll get insertions from each child in
@@ -2048,7 +2041,7 @@ function commitDeletionEffectsOnFiber(
2041 // Fall through
2042 }
2043 case HostSingleton: {
2051 - if (enableHostSingletons && supportsSingletons) {
2044 + if (supportsSingletons) {
2045 if (!offscreenSubtreeWasHidden) {
2046 safelyDetachRef(deletedFiber, nearestMountedAncestor);
2047 }
@@ -2711,7 +2704,7 @@ function commitMutationEffectsOnFiber(
2704 // Fall through
2705 }
2706 case HostSingleton: {
2714 - if (enableHostSingletons && supportsSingletons) {
2707 + if (supportsSingletons) {
2708 if (flags & Update) {
2709 const previousWork = finishedWork.alternate;
2710 if (previousWork === null) {
packages/react-reconciler/src/ReactFiberCompleteWork.js
+2 -5
@@ -33,7 +33,6 @@ import type {TracingMarkerInstance} from './ReactFiberTracingMarkerComponent';
33 import type {Cache} from './ReactFiberCacheComponent';
34 import {
35 enableLegacyHidden,
36 - enableHostSingletons,
36 enableSuspenseCallback,
37 enableScopeAPI,
38 enableProfilerTimer,
@@ -233,9 +232,7 @@ function appendAllChildren(
232 appendInitialChild(parent, node.stateNode);
233 } else if (
234 node.tag === HostPortal ||
236 - (enableHostSingletons && supportsSingletons
237 - ? node.tag === HostSingleton
238 - : false)
235 + (supportsSingletons ? node.tag === HostSingleton : false)
236 ) {
237 // If we have a portal child, then we don't want to traverse
238 // down its children. Instead, we'll get insertions from each child in
@@ -1177,7 +1174,7 @@ function completeWork(
1174 // Fall through
1175 }
1176 case HostSingleton: {
1180 - if (enableHostSingletons && supportsSingletons) {
1177 + if (supportsSingletons) {
1178 popHostContext(workInProgress);
1179 const rootContainerInstance = getRootHostContainer();
1180 const type = workInProgress.type;
packages/react-reconciler/src/ReactFiberHotReloading.js
+2 -4
@@ -14,7 +14,7 @@ import type {Fiber, FiberRoot} from './ReactInternalTypes';
14 import type {Instance} from './ReactFiberConfig';
15 import type {ReactNodeList} from 'shared/ReactTypes';
16
17 -import {enableHostSingletons, enableFloat} from 'shared/ReactFeatureFlags';
17 +import {enableFloat} from 'shared/ReactFeatureFlags';
18 import {
19 flushSync,
20 scheduleUpdateOnFiber,
@@ -469,9 +469,7 @@ function findChildHostInstancesForFiberShallowly(
469 if (
470 node.tag === HostComponent ||
471 (enableFloat ? node.tag === HostHoistable : false) ||
472 - (enableHostSingletons && supportsSingletons
473 - ? node.tag === HostSingleton
474 - : false)
472 + (supportsSingletons ? node.tag === HostSingleton : false)
473 ) {
474 // We got a match.
475 foundHostInstances = true;
packages/react-reconciler/src/ReactFiberHydrationContext.js
+3 -6
@@ -35,10 +35,7 @@ import {
35 NoFlags,
36 DidCapture,
37 } from './ReactFiberFlags';
38 -import {
39 - enableHostSingletons,
40 - enableClientRenderFallbackOnTextMismatch,
41 -} from 'shared/ReactFeatureFlags';
38 +import {enableClientRenderFallbackOnTextMismatch} from 'shared/ReactFeatureFlags';
39
40 import {
41 createFiberFromHostInstanceForDeletion,
@@ -426,7 +423,7 @@ function throwOnHydrationMismatch(fiber: Fiber) {
423 }
424
425 function claimHydratableSingleton(fiber: Fiber): void {
429 - if (enableHostSingletons && supportsSingletons) {
426 + if (supportsSingletons) {
427 if (!isHydrating) {
428 return;
429 }
@@ -801,7 +798,7 @@ function popHydrationState(fiber: Fiber): boolean {
798 }
799
800 let shouldClear = false;
804 - if (enableHostSingletons && supportsSingletons) {
801 + if (supportsSingletons) {
802 // With float we never clear the Root, or Singleton instances. We also do not clear Instances
803 // that have singleton text content
804 if (
packages/react-reconciler/src/ReactFiberTreeReflection.js
+3 -3
@@ -25,7 +25,7 @@ import {
25 SuspenseComponent,
26 } from './ReactWorkTags';
27 import {NoFlags, Placement, Hydrating} from './ReactFiberFlags';
28 -import {enableFloat, enableHostSingletons} from 'shared/ReactFeatureFlags';
28 +import {enableFloat} from 'shared/ReactFeatureFlags';
29
30 const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
31
@@ -281,7 +281,7 @@ function findCurrentHostFiberImpl(node: Fiber): Fiber | null {
281 if (
282 tag === HostComponent ||
283 (enableFloat ? tag === HostHoistable : false) ||
284 - (enableHostSingletons ? tag === HostSingleton : false) ||
284 + tag === HostSingleton ||
285 tag === HostText
286 ) {
287 return node;
@@ -312,7 +312,7 @@ function findCurrentHostFiberWithNoPortalsImpl(node: Fiber): Fiber | null {
312 if (
313 tag === HostComponent ||
314 (enableFloat ? tag === HostHoistable : false) ||
315 - (enableHostSingletons ? tag === HostSingleton : false) ||
315 + tag === HostSingleton ||
316 tag === HostText
317 ) {
318 return node;
packages/shared/ReactFeatureFlags.js
-2
@@ -105,8 +105,6 @@ export const enableSuspenseAvoidThisFallbackFizz = false;
105
106 export const enableCPUSuspense = __EXPERIMENTAL__;
107
108 -export const enableHostSingletons = true;
109 -
108 export const enableFloat = true;
109
110 // Enables unstable_useMemoCache hook, intended as a compilation target for
packages/shared/forks/ReactFeatureFlags.native-fb.js
-1
@@ -83,7 +83,6 @@ export const enableServerContext = false;
83 export const enableTransitionTracing = false;
84
85 export const enableFloat = true;
86 -export const enableHostSingletons = true;
86
87 export const useModernStrictMode = false;
88 export const enableDO_NOT_USE_disableStrictPassiveEffect = false;
packages/shared/forks/ReactFeatureFlags.native-oss.js
-1
@@ -68,7 +68,6 @@ export const enableServerContext = false;
68 export const enableTransitionTracing = false;
69
70 export const enableFloat = true;
71 -export const enableHostSingletons = true;
71
72 export const useModernStrictMode = false;
73 export const enableDO_NOT_USE_disableStrictPassiveEffect = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.js
-1
@@ -68,7 +68,6 @@ export const enableServerContext = false;
68 export const enableTransitionTracing = false;
69
70 export const enableFloat = true;
71 -export const enableHostSingletons = true;
71
72 export const useModernStrictMode = false;
73 export const enableDO_NOT_USE_disableStrictPassiveEffect = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.native.js
-1
@@ -66,7 +66,6 @@ export const enableServerContext = false;
66 export const enableTransitionTracing = false;
67
68 export const enableFloat = true;
69 -export const enableHostSingletons = true;
69
70 export const useModernStrictMode = false;
71 export const enableDO_NOT_USE_disableStrictPassiveEffect = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
-1
@@ -68,7 +68,6 @@ export const enableServerContext = false;
68 export const enableTransitionTracing = false;
69
70 export const enableFloat = true;
71 -export const enableHostSingletons = true;
71
72 export const useModernStrictMode = false;
73 export const enableDO_NOT_USE_disableStrictPassiveEffect = false;
packages/shared/forks/ReactFeatureFlags.www.js
-1
@@ -54,7 +54,6 @@ export const enableCPUSuspense = true;
54 export const enableFloat = true;
55 export const enableUseMemoCacheHook = true;
56 export const enableUseEffectEventHook = true;
57 -export const enableHostSingletons = true;
57 export const enableClientRenderFallbackOnTextMismatch = false;
58 export const enableFilterEmptyStringAttributesDOM = true;
59