Fixes #9667: Updated createTextInstance to create the text node on correct document (#10723)
Kenneth Chau committed
Sep 22, 2017 at 16:08 UTC
a160f3ecfa2fff67d8dec9c22a63300b78d3ad0c
3 files changed
+49
-5
src/renderers/dom/fiber/ReactDOMFiberComponent.js
+17
-4
@@ -157,6 +157,14 @@ function ensureListeningTo(rootContainerElement, registrationName) {
157
listenTo(registrationName, doc);
158
}
159
160
+function getOwnerDocumentFromRootContainer(
161
+ rootContainerElement: Element | Document,
162
+): Document {
163
+ return rootContainerElement.nodeType === DOCUMENT_NODE
164
+ ? (rootContainerElement: any)
165
+ : rootContainerElement.ownerDocument;
166
+}
167
+
168
// There are so many media events, it makes sense to just
169
// maintain a list rather than create a `trapBubbledEvent` for each
170
var mediaEvents = {
@@ -296,10 +304,9 @@ var ReactDOMFiberComponent = {
304
): Element {
305
// We create tags in the namespace of their parent container, except HTML
306
// tags get no namespace.
299
- var ownerDocument: Document = rootContainerElement.nodeType ===
300
- DOCUMENT_NODE
301
- ? (rootContainerElement: any)
302
- : rootContainerElement.ownerDocument;
307
+ var ownerDocument: Document = getOwnerDocumentFromRootContainer(
308
+ rootContainerElement,
309
+ );
310
var domElement: Element;
311
var namespaceURI = parentNamespace;
312
if (namespaceURI === HTML_NAMESPACE) {
@@ -362,6 +369,12 @@ var ReactDOMFiberComponent = {
369
return domElement;
370
},
371
372
+ createTextNode(text: string, rootContainerElement: Element | Document): Text {
373
+ return getOwnerDocumentFromRootContainer(
374
+ rootContainerElement,
375
+ ).createTextNode(text);
376
+ },
377
+
378
setInitialProperties(
379
domElement: Element,
380
tag: string,
src/renderers/dom/fiber/ReactDOMFiberEntry.js
+2
-1
@@ -46,6 +46,7 @@ var invariant = require('fbjs/lib/invariant');
46
var {getChildNamespace} = DOMNamespaces;
47
var {
48
createElement,
49
+ createTextNode,
50
setInitialProperties,
51
diffProperties,
52
updateProperties,
@@ -368,7 +369,7 @@ var DOMRenderer = ReactFiberReconciler({
369
const hostContextDev = ((hostContext: any): HostContextDev);
370
validateDOMNesting(null, text, null, hostContextDev.ancestorInfo);
371
}
371
- var textNode: TextInstance = document.createTextNode(text);
372
+ var textNode: TextInstance = createTextNode(text, rootContainerInstance);
373
precacheFiberNode(internalInstanceHandle, textNode);
374
return textNode;
375
},
src/renderers/dom/fiber/__tests__/ReactDOMFiber-test.js
+30
@@ -1117,5 +1117,35 @@ describe('ReactDOMFiber', () => {
1117
'to empty a container.',
1118
);
1119
});
1120
+
1121
+ it('should render a text component with a text DOM node on the same document as the container', () => {
1122
+ // 1. Create a new document through the use of iframe
1123
+ // 2. Set up the spy to make asserts when a text component
1124
+ // is rendered inside the iframe container
1125
+ var textContent = 'Hello world';
1126
+ var iframe = document.createElement('iframe');
1127
+ document.body.appendChild(iframe);
1128
+ var iframeDocument = iframe.contentDocument;
1129
+ iframeDocument.write(
1130
+ '<!DOCTYPE html><html><head></head><body><div></div></body></html>',
1131
+ );
1132
+ iframeDocument.close();
1133
+ var iframeContainer = iframeDocument.body.firstChild;
1134
+
1135
+ var actualDocument;
1136
+ var textNode;
1137
+
1138
+ spyOn(iframeContainer, 'appendChild').and.callFake(node => {
1139
+ actualDocument = node.ownerDocument;
1140
+ textNode = node;
1141
+ });
1142
+
1143
+ ReactDOM.render(textContent, iframeContainer);
1144
+
1145
+ expect(textNode.textContent).toBe(textContent);
1146
+ expect(actualDocument).not.toBe(document);
1147
+ expect(actualDocument).toBe(iframeDocument);
1148
+ expect(iframeContainer.appendChild).toHaveBeenCalledTimes(1);
1149
+ });
1150
}
1151
});