[Fiber] Fix rendering SVG into non-React SVG tree (#8638)
* Add a test for rendering SVG into a non-React SVG tree It is failing in Fiber. * Add a test for rendering HTML into non-React foreignObject It happens to pass in Fiber. * Determine root namespace by container namespace, not just tag A tag alone is not enough to determine the tree namespace. * Skip the test that exhibits jsdom bug in non-createElement mode jsdom doesn't give HTML namespace to foreignObject.innerHTML children. This problem doesn't exist in the browsers. https://github.com/facebook/react/pull/8638#issuecomment-269349642 We will skip this test in non-createElement mode considering that non-createElement mounting is effectively dead code now anyway.
Dan Abramov committed
Jan 14, 2017 at 05:11 UTC
6a488913b96b3f3f1c8e065b51c3966b148ad135
3 files changed
+45
-4
scripts/fiber/tests-passing.txt
+2
@@ -738,6 +738,8 @@ src/renderers/dom/shared/__tests__/ReactDOMSVG-test.js
738
* creates initial namespaced markup
739
* creates elements with SVG namespace inside SVG tag during mount
740
* creates elements with SVG namespace inside SVG tag during update
741
+* can render SVG into a non-React SVG tree
742
+* can render HTML into a foreignObject in non-React SVG tree
743
744
src/renderers/dom/shared/__tests__/ReactDOMTextComponent-test.js
745
* updates a mounted text component in place
src/renderers/dom/fiber/ReactDOMFiber.js
+6
-4
@@ -116,14 +116,16 @@ function shouldAutoFocusHostComponent(
116
var DOMRenderer = ReactFiberReconciler({
117
118
getRootHostContext(rootContainerInstance : Container) : HostContext {
119
- const type = rootContainerInstance.tagName.toLowerCase();
119
+ const ownNamespace = rootContainerInstance.namespaceURI || null;
120
+ const type = rootContainerInstance.tagName;
121
+ const namespace = getChildNamespace(ownNamespace, type);
122
if (__DEV__) {
121
- const namespace = getChildNamespace(null, type);
123
const isMountingIntoDocument = rootContainerInstance.ownerDocument.documentElement === rootContainerInstance;
123
- const ancestorInfo = updatedAncestorInfo(null, isMountingIntoDocument ? '#document' : type, null);
124
+ const validatedTag = isMountingIntoDocument ? '#document' : type.toLowerCase();
125
+ const ancestorInfo = updatedAncestorInfo(null, validatedTag, null);
126
return {namespace, ancestorInfo};
127
}
126
- return getChildNamespace(null, type);
128
+ return namespace;
129
},
130
131
getChildHostContext(
src/renderers/dom/shared/__tests__/ReactDOMSVG-test.js
+37
@@ -13,6 +13,7 @@
13
14
var React;
15
var ReactDOM;
16
+var ReactDOMFeatureFlags;
17
var ReactDOMServer;
18
19
describe('ReactDOMSVG', () => {
@@ -20,6 +21,7 @@ describe('ReactDOMSVG', () => {
21
beforeEach(() => {
22
React = require('React');
23
ReactDOM = require('ReactDOM');
24
+ ReactDOMFeatureFlags = require('ReactDOMFeatureFlags');
25
ReactDOMServer = require('ReactDOMServer');
26
});
27
@@ -157,4 +159,39 @@ describe('ReactDOMSVG', () => {
159
});
160
});
161
162
+ it('can render SVG into a non-React SVG tree', () => {
163
+ var outerSVGRoot = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
164
+ var container = document.createElementNS('http://www.w3.org/2000/svg', 'g');
165
+ outerSVGRoot.appendChild(container);
166
+ var image;
167
+ ReactDOM.render(
168
+ <image ref={el => image = el} />,
169
+ container
170
+ );
171
+ expect(image.namespaceURI).toBe('http://www.w3.org/2000/svg');
172
+ expect(image.tagName).toBe('image');
173
+ });
174
+
175
+ it('can render HTML into a foreignObject in non-React SVG tree', () => {
176
+ if (!ReactDOMFeatureFlags.useCreateElement) {
177
+ // jsdom doesn't give HTML namespace to foreignObject.innerHTML children.
178
+ // This problem doesn't exist in the browsers.
179
+ // https://github.com/facebook/react/pull/8638#issuecomment-269349642
180
+ // We will skip this test in non-createElement mode considering
181
+ // that non-createElement mounting is effectively dead code now anyway.
182
+ return;
183
+ }
184
+
185
+ var outerSVGRoot = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
186
+ var container = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject');
187
+ outerSVGRoot.appendChild(container);
188
+ var div;
189
+ ReactDOM.render(
190
+ <div ref={el => div = el} />,
191
+ container
192
+ );
193
+ expect(div.namespaceURI).toBe('http://www.w3.org/1999/xhtml');
194
+ expect(div.tagName).toBe('DIV');
195
+ });
196
+
197
});