@@ -32,7 +32,6 @@ import {
32
32
setInitialProperties,
33
33
diffProperties,
34
34
updateProperties,
35
- resetProperties,
36
35
diffHydratedProperties,
37
36
diffHydratedText,
38
37
trapClickOnNonInteractiveElement,
@@ -124,7 +123,6 @@ export type Container =
124
123
| interface extends Document {_reactRootContainer?: FiberRoot}
125
124
| interface extends DocumentFragment {_reactRootContainer?: FiberRoot};
126
125
export type Instance = Element;
127
- export type InstanceSibling = Node;
128
126
export type TextInstance = Text;
129
127
export interface SuspenseInstance extends Comment {
130
128
_reactRetry?: () => void;
@@ -552,15 +550,15 @@ export function appendChildToContainer(
552
550
export function insertBefore(
553
551
parentInstance: Instance,
554
552
child: Instance | TextInstance,
555
- beforeChild: InstanceSibling ,
553
+ beforeChild: Instance ,
556
554
): void {
557
555
parentInstance.insertBefore(child, beforeChild);
558
556
}
559
557
560
558
export function insertInContainerBefore(
561
559
container: Container,
562
560
child: Instance | TextInstance,
563
- beforeChild: InstanceSibling ,
561
+ beforeChild: Instance ,
564
562
): void {
565
563
if (container.nodeType === COMMENT_NODE) {
566
564
(container.parentNode: any).insertBefore(child, beforeChild);
@@ -717,15 +715,32 @@ export function clearContainer(container: Container): void {
717
715
case 'html':
718
716
case 'head':
719
717
case 'body': {
720
- clearSingletonInstance(element);
721
- break;
718
+ let node = element.firstChild;
719
+ while (node) {
720
+ const nextNode = node.nextSibling;
721
+ const nodeName = node.nodeName;
722
+ if (
723
+ nodeName === 'HEAD' ||
724
+ nodeName === 'BODY' ||
725
+ nodeName === 'STYLE' ||
726
+ (nodeName === 'LINK' &&
727
+ ((node: any): HTMLLinkElement).rel.toLowerCase() ===
728
+ 'stylesheet')
729
+ ) {
730
+ // retain these nodes
731
+ } else {
732
+ element.removeChild(node);
733
+ }
734
+ node = nextNode;
735
+ }
736
+ return;
722
737
}
723
738
default: {
724
739
element.textContent = '';
725
740
}
726
741
}
727
742
}
728
- // Implicitly if the container is of type Document we rely on the Persistent HostComponent
743
+ // Implicitly if the container is of type Document we rely on the HostSingleton
729
744
// semantics to clear these nodes appropriately when being placed so no ahead of time
730
745
// clearing is necessary
731
746
} else {
@@ -1246,7 +1261,7 @@ export function errorHydratingContainer(parentContainer: Container): void {
1246
1261
}
1247
1262
}
1248
1263
1249
- export function acquireSingletonInstance (
1264
+ export function resolveSingletonInstance (
1250
1265
type: string,
1251
1266
props: Props,
1252
1267
rootContainerInstance: Container,
@@ -1262,50 +1277,51 @@ export function acquireSingletonInstance(
1262
1277
const ownerDocument = getOwnerDocumentFromRootContainer(
1263
1278
rootContainerInstance,
1264
1279
);
1265
- // For the three persistent Host Components that exist in DOM it is necessary for there to
1266
- // always be a documentElement. With normal html parsing this will always be the case but
1267
- // with pathological manipulation the document can end up in a state where no documentElement
1268
- // exists. We create it here if missing so we can treat it as an invariant.
1269
- // It is important to note that this dom mutation and others in this function happen
1270
- // in render rather than commit. This is tolerable because they only happen in degenerate cases
1271
- let htmlElement = ownerDocument.documentElement;
1272
- if (!htmlElement) {
1273
- htmlElement = ownerDocument.appendChild(
1274
- ownerDocument.createElement('html'),
1275
- );
1276
- }
1277
1280
switch (type) {
1278
1281
case 'html': {
1279
- return htmlElement;
1282
+ const documentElement = ownerDocument.documentElement;
1283
+ if (!documentElement) {
1284
+ throw new Error(
1285
+ 'React expected an <html> element (document.documentElement) to exist in the Document but one was' +
1286
+ ' not found. React never removes the documentElement for any Document it renders into so' +
1287
+ ' the cause is likely in some other script running on this page.',
1288
+ );
1289
+ }
1290
+ return documentElement;
1280
1291
}
1281
1292
case 'head': {
1282
- let head = ownerDocument.head;
1293
+ const head = ownerDocument.head;
1283
1294
if (!head) {
1284
- head = htmlElement.insertBefore(
1285
- ownerDocument.createElement('head'),
1286
- ownerDocument.firstChild,
1295
+ throw new Error(
1296
+ 'React expected a <head> element (document.head) to exist in the Document but one was' +
1297
+ ' not found. React never removes the head for any Document it renders into so' +
1298
+ ' the cause is likely in some other script running on this page.',
1287
1299
);
1288
1300
}
1289
1301
// We ensure this exists just above
1290
1302
return head;
1291
1303
}
1292
1304
case 'body': {
1293
- let body = ownerDocument.body;
1305
+ const body = ownerDocument.body;
1294
1306
if (!body) {
1295
- body = htmlElement.appendChild(ownerDocument.createElement('body'));
1307
+ throw new Error(
1308
+ 'React expected a <body> element (document.body) to exist in the Document but one was' +
1309
+ ' not found. React never removes the body for any Document it renders into so' +
1310
+ ' the cause is likely in some other script running on this page.',
1311
+ );
1296
1312
}
1297
1313
// We ensure this exists just above
1298
1314
return body;
1299
1315
}
1300
1316
default: {
1301
1317
throw new Error(
1302
- 'acquireSingletonInstance was called with an element type that is not supported. This is a bug in React.',
1318
+ 'resolveSingletonInstance was called with an element type that is not supported. This is a bug in React.',
1303
1319
);
1304
1320
}
1305
1321
}
1306
1322
}
1307
1323
1308
- export function resetSingletonInstance (
1324
+ export function acquireSingletonInstance (
1309
1325
type: string,
1310
1326
props: Props,
1311
1327
instance: Instance,
@@ -1320,51 +1336,17 @@ export function resetSingletonInstance(
1320
1336
}
1321
1337
default: {
1322
1338
console.error(
1323
- 'resetSingletonInstance was called with an element type that is not supported. This is a bug in React.',
1339
+ 'acquireSingletonInstance was called with an element type that is not supported. This is a bug in React.',
1324
1340
);
1325
1341
}
1326
1342
}
1327
1343
}
1328
1344
1329
- clearSingletonInstance(instance);
1330
- resetProperties(instance, type, props);
1345
+ setInitialProperties(instance, type, props);
1331
1346
precacheFiberNode(internalInstanceHandle, instance);
1332
1347
updateFiberProps(instance, props);
1333
1348
}
1334
1349
1335
- export function clearSingletonInstance(instance: Instance) {
1336
- const tagName = instance.tagName.toLowerCase();
1337
- switch (tagName) {
1338
- case 'html': {
1339
- return;
1340
- }
1341
- case 'head':
1342
- case 'body': {
1343
- let node = instance.firstChild;
1344
- while (node) {
1345
- const nextNode = node.nextSibling;
1346
- const nodeName = node.nodeName;
1347
- if (
1348
- nodeName === 'STYLE' ||
1349
- (nodeName === 'LINK' &&
1350
- ((node: any): HTMLLinkElement).rel.toLowerCase() === 'stylesheet')
1351
- ) {
1352
- // retain these nodes
1353
- } else {
1354
- instance.removeChild(node);
1355
- }
1356
- node = nextNode;
1357
- }
1358
- return;
1359
- }
1360
- default: {
1361
- throw new Error(
1362
- 'clearSingletonInstance was called with an element type that is not supported. this is a bug in React.',
1363
- );
1364
- }
1365
- }
1366
- }
1367
-
1368
1350
// -------------------
1369
1351
// Test Selectors
1370
1352
// -------------------
0 commit comments