@samitouri / QOS-React / commits / 6a488913b9

[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 });