[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