diff --git a/src/renderers/dom/client/utils/DOMLazyTree.js b/src/renderers/dom/client/utils/DOMLazyTree.js
index 269f5c37145a2..c6c0b98f9e8ec 100644
--- a/src/renderers/dom/client/utils/DOMLazyTree.js
+++ b/src/renderers/dom/client/utils/DOMLazyTree.js
@@ -12,6 +12,7 @@
'use strict';
var DOMNamespaces = require('DOMNamespaces');
+var setInnerHTML = require('setInnerHTML');
var createMicrosoftUnsafeLocalFunction = require('createMicrosoftUnsafeLocalFunction');
var setTextContent = require('setTextContent');
@@ -50,7 +51,7 @@ function insertTreeChildren(tree) {
insertTreeBefore(node, children[i], null);
}
} else if (tree.html != null) {
- node.innerHTML = tree.html;
+ setInnerHTML(node, tree.html);
} else if (tree.text != null) {
setTextContent(node, tree.text);
}
@@ -96,7 +97,7 @@ function queueHTML(tree, html) {
if (enableLazy) {
tree.html = html;
} else {
- tree.node.innerHTML = html;
+ setInnerHTML(tree.node, html);
}
}
diff --git a/src/renderers/dom/client/utils/__tests__/setInnerHTML.js b/src/renderers/dom/client/utils/__tests__/setInnerHTML.js
new file mode 100644
index 0000000000000..2f4eccec4e8eb
--- /dev/null
+++ b/src/renderers/dom/client/utils/__tests__/setInnerHTML.js
@@ -0,0 +1,42 @@
+/**
+ * Copyright 2016-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @emails react-core
+ */
+
+'use strict';
+
+var setInnerHTML = require('setInnerHTML');
+var DOMNamespaces = require('DOMNamespaces');
+
+describe('setInnerHTML', function() {
+ describe('when the node has innerHTML property', () => {
+ it('sets innerHTML on it', function() {
+ var node = document.createElement('div');
+ var html = '
hello
';
+ setInnerHTML(node, html);
+ expect(node.innerHTML).toBe(html);
+ });
+ });
+
+ describe('when the node does not have an innerHTML property', () => {
+ it('sets innerHTML on it', function() {
+ // Create a mock node that looks like an SVG in IE (without innerHTML)
+ var node = {
+ namespaceURI: DOMNamespaces.svg,
+ appendChild: jasmine.createSpy(),
+ };
+
+ var html = '';
+ setInnerHTML(node, html);
+
+ expect(node.appendChild.calls.argsFor(0)[0].outerHTML).toBe('');
+ expect(node.appendChild.calls.argsFor(1)[0].outerHTML).toBe('');
+ });
+ });
+});
diff --git a/src/renderers/dom/client/utils/setInnerHTML.js b/src/renderers/dom/client/utils/setInnerHTML.js
index 1e491bfaf3820..59348fe3c3f70 100644
--- a/src/renderers/dom/client/utils/setInnerHTML.js
+++ b/src/renderers/dom/client/utils/setInnerHTML.js
@@ -12,12 +12,16 @@
'use strict';
var ExecutionEnvironment = require('ExecutionEnvironment');
+var DOMNamespaces = require('DOMNamespaces');
var WHITESPACE_TEST = /^[ \r\n\t\f]/;
var NONVISIBLE_TEST = /<(!--|link|noscript|meta|script|style)[ \r\n\t\f\/>]/;
var createMicrosoftUnsafeLocalFunction = require('createMicrosoftUnsafeLocalFunction');
+// SVG temp container for IE lacking innerHTML
+var reusableSVGContainer;
+
/**
* Set the innerHTML property of a node, ensuring that whitespace is preserved
* even in IE8.
@@ -28,7 +32,19 @@ var createMicrosoftUnsafeLocalFunction = require('createMicrosoftUnsafeLocalFunc
*/
var setInnerHTML = createMicrosoftUnsafeLocalFunction(
function(node, html) {
- node.innerHTML = html;
+ // IE does not have innerHTML for SVG nodes, so instead we inject the
+ // new markup in a temp node and then move the child nodes across into
+ // the target node
+ if (node.namespaceURI === DOMNamespaces.svg && !('innerHTML' in node)) {
+ reusableSVGContainer = reusableSVGContainer || document.createElement('div');
+ reusableSVGContainer.innerHTML = '';
+ var newNodes = reusableSVGContainer.firstChild.childNodes;
+ for (var i = 0; i < newNodes.length; i++) {
+ node.appendChild(newNodes[i]);
+ }
+ } else {
+ node.innerHTML = html;
+ }
}
);