diff --git a/src/components/icon/icon.spec.js b/src/components/icon/icon.spec.js
index cf6ef75ed8..2cd82d508a 100644
--- a/src/components/icon/icon.spec.js
+++ b/src/components/icon/icon.spec.js
@@ -593,6 +593,22 @@ describe('MdIcon service', function() {
$scope.$digest();
});
+ // This covers a case where we saw a g3 test using an empty and it could
+ // throw an exception "Looking up elements via selectors is not supported by jqLite!"
+ // if proper checks weren't in place in the transformClone() code.
+ it('should handle empty SVGs', function() {
+ // Just request the icon to be stored in the cache.
+ $mdIcon('emptyGroup.svg');
+
+ $scope.$digest();
+
+ $mdIcon('emptyGroup.svg').then(function(el) {
+ expect(el).toBeTruthy();
+ });
+
+ $scope.$digest();
+ });
+
it('should suffix duplicated ids and refs', function() {
// Just request the icon to be stored in the cache.
$mdIcon('angular-logo.svg');
diff --git a/src/components/icon/js/iconService.js b/src/components/icon/js/iconService.js
index 6bbd34c552..987c9d3999 100644
--- a/src/components/icon/js/iconService.js
+++ b/src/components/icon/js/iconService.js
@@ -350,14 +350,14 @@ MdIconProvider.prototype = {
/**
* Configuration item stored in the Icon registry; used for lookups
* to load if not already cached in the `loaded` cache
- * @param url
- * @param viewBoxSize
+ * @param {string} url
+ * @param {=number} viewBoxSize
* @constructor
*/
function ConfigurationItem(url, viewBoxSize) {
- this.url = url;
- this.viewBoxSize = viewBoxSize || config.defaultViewBoxSize;
-}
+ this.url = url;
+ this.viewBoxSize = viewBoxSize || config.defaultViewBoxSize;
+ }
/**
* @ngdoc service
@@ -473,13 +473,13 @@ function MdIconService(config, $templateRequest, $q, $log, $mdUtil, $sce) {
}
/**
- * @param {Icon} cacheElement cached icon from the iconCache
+ * @param {!Icon} cacheElement cached icon from the iconCache
* @returns {Icon} cloned Icon element with unique ids
*/
function transformClone(cacheElement) {
var clone = cacheElement.clone();
var newUid = $mdUtil.nextUid();
- var cacheSuffix;
+ var cacheSuffix, svgElement;
// Verify that the newUid only contains a number and not some XSS content.
if (!isFinite(Number(newUid))) {
@@ -501,11 +501,19 @@ function MdIconService(config, $templateRequest, $q, $log, $mdUtil, $sce) {
angular.forEach(clone.querySelectorAll('[id]'), function(descendantElem) {
descendantElem.id += cacheSuffix;
});
- // Inject the cacheSuffix into all instances of url(id) and xlink:href="#id".
- // This use of innerHTML should be safe from XSS attack since we are only injecting the
- // cacheSuffix with content from $mdUtil.nextUid which we verify is a finite number above.
- clone.innerHTML = clone.innerHTML.replace(/(.*url\(#)(\w*)(\).*)/g, addCacheSuffixToId);
- clone.innerHTML = clone.innerHTML.replace(/(.*xlink:href="#)(\w*)(".*)/g, addCacheSuffixToId);
+ // innerHTML of SVG elements is not supported by IE11
+ if (clone.innerHTML === undefined) {
+ svgElement = $mdUtil.getInnerHTML(clone);
+ svgElement = svgElement.replace(/(.*url\(#)(\w*)(\).*)/g, addCacheSuffixToId);
+ svgElement = svgElement.replace(/(.*xlink:href="#)(\w*)(".*)/g, addCacheSuffixToId);
+ clone = angular.element(svgElement)[0];
+ } else {
+ // Inject the cacheSuffix into all instances of url(id) and xlink:href="#id".
+ // This use of innerHTML should be safe from XSS attack since we are only injecting the
+ // cacheSuffix with content from $mdUtil.nextUid which we verify is a finite number above.
+ clone.innerHTML = clone.innerHTML.replace(/(.*url\(#)(\w*)(\).*)/g, addCacheSuffixToId);
+ clone.innerHTML = clone.innerHTML.replace(/(.*xlink:href="#)(\w*)(".*)/g, addCacheSuffixToId);
+ }
return clone;
}
@@ -605,24 +613,37 @@ function MdIconService(config, $templateRequest, $q, $log, $mdUtil, $sce) {
/**
* Check target signature to see if it is an Icon instance.
+ * @param {Icon|Element} target
+ * @returns {boolean} true if the specified target is an Icon object, false otherwise.
*/
function isIcon(target) {
return angular.isDefined(target.element) && angular.isDefined(target.config);
}
/**
- * Define the Icon class
+ * Define the Icon class
+ * @param {Element} el
+ * @param {=ConfigurationItem} config
+ * @constructor
*/
function Icon(el, config) {
+ var elementContents;
// If the node is a , it won't be rendered so we have to convert it into