diff --git a/src/Angular.js b/src/Angular.js index 15d313d7b104..50038de77f75 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -825,6 +825,8 @@ function copy(source, destination, stackSource, stackDest) { } else if (isRegExp(source)) { destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]); destination.lastIndex = source.lastIndex; + } else if (isFunction(source.cloneNode)) { + destination = source.cloneNode(true); } else { var emptyObject = Object.create(getPrototypeOf(source)); return copy(source, emptyObject, stackSource, stackDest); diff --git a/test/AngularSpec.js b/test/AngularSpec.js index fd7f6e43bce3..7a21a0feea39 100644 --- a/test/AngularSpec.js +++ b/test/AngularSpec.js @@ -386,6 +386,18 @@ describe('angular', function() { expect(aCopy).toBe(aCopy.self); }); + it('should deeply copy XML nodes', function() { + var anElement = document.createElement('foo'); + anElement.appendChild(document.createElement('bar')); + var theCopy = anElement.cloneNode(true); + expect(copy(anElement).outerHTML).toEqual(theCopy.outerHTML); + expect(copy(anElement)).not.toBe(anElement); + }); + + it('should not try to call a non-function called `cloneNode`', function() { + expect(copy.bind(null, { cloneNode: 100 })).not.toThrow(); + }); + it('should handle objects with multiple references', function() { var b = {}; var a = [b, -1, b];