Bug 1359556 - Optimize cloneNode by preinitializing attribute and child arrays r=bz
authorKirk Steuber <ksteuber@mozilla.com>
Thu, 20 Apr 2017 12:57:48 -0700
changeset 403749 c6af127dce9d85ee8c42b13235b5fa6133d3a0e2
parent 403748 6c6f75a1e3cca21352d93cb3958c0114fd20ded8
child 403750 796fdd50c2eb345382ec7ae3479dfdfece8cdf80
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1359556
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1359556 - Optimize cloneNode by preinitializing attribute and child arrays r=bz Currently, attribute and child arrays (implemented in dom/base/nsAttrAndChildArray.h) start out empty. When cloning, the array ends up being resized multiple times in order to add the attributes and children that are being cloned from the original node. This would be quicker if the array was initialized to the correct size in the first place so that resizes are not necessary. However, preallocating space for children is only necessary when performing a deep clone. Therefore, an additional parameter is being added to the Clone, CopyInnerTo, and CloneDocHelper methods to indicate whether preallocation of children should happen. Attributes are copied either way, so that part of the array is preallocated in both cases. MozReview-Commit-ID: 3iVezeAKXnI
dom/base/Attr.cpp
dom/base/Attr.h
dom/base/DocumentFragment.h
dom/base/Element.h
dom/base/FragmentOrElement.cpp
dom/base/FragmentOrElement.h
dom/base/ShadowRoot.cpp
dom/base/ShadowRoot.h
dom/base/nsAttrAndChildArray.cpp
dom/base/nsAttrAndChildArray.h
dom/base/nsDocument.cpp
dom/base/nsDocument.h
dom/base/nsGenericDOMDataNode.h
dom/base/nsINode.h
dom/base/nsNodeUtils.cpp
dom/html/HTMLAnchorElement.h
dom/html/HTMLAreaElement.h
dom/html/HTMLAudioElement.h
dom/html/HTMLBRElement.h
dom/html/HTMLBodyElement.h
dom/html/HTMLButtonElement.h
dom/html/HTMLCanvasElement.cpp
dom/html/HTMLCanvasElement.h
dom/html/HTMLContentElement.h
dom/html/HTMLDataElement.h
dom/html/HTMLDataListElement.h
dom/html/HTMLDetailsElement.h
dom/html/HTMLDialogElement.h
dom/html/HTMLDivElement.h
dom/html/HTMLElement.cpp
dom/html/HTMLFieldSetElement.h
dom/html/HTMLFontElement.h
dom/html/HTMLFormElement.h
dom/html/HTMLFrameElement.h
dom/html/HTMLFrameSetElement.h
dom/html/HTMLHRElement.h
dom/html/HTMLHeadingElement.h
dom/html/HTMLIFrameElement.h
dom/html/HTMLImageElement.cpp
dom/html/HTMLImageElement.h
dom/html/HTMLInputElement.cpp
dom/html/HTMLInputElement.h
dom/html/HTMLLIElement.h
dom/html/HTMLLabelElement.h
dom/html/HTMLLegendElement.h
dom/html/HTMLLinkElement.h
dom/html/HTMLMapElement.h
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
dom/html/HTMLMenuElement.h
dom/html/HTMLMenuItemElement.cpp
dom/html/HTMLMenuItemElement.h
dom/html/HTMLMetaElement.h
dom/html/HTMLMeterElement.h
dom/html/HTMLModElement.h
dom/html/HTMLObjectElement.cpp
dom/html/HTMLObjectElement.h
dom/html/HTMLOptGroupElement.h
dom/html/HTMLOptionElement.cpp
dom/html/HTMLOptionElement.h
dom/html/HTMLOutputElement.h
dom/html/HTMLParagraphElement.h
dom/html/HTMLPictureElement.h
dom/html/HTMLPreElement.h
dom/html/HTMLProgressElement.h
dom/html/HTMLScriptElement.cpp
dom/html/HTMLScriptElement.h
dom/html/HTMLSelectElement.h
dom/html/HTMLShadowElement.h
dom/html/HTMLSharedElement.h
dom/html/HTMLSharedListElement.h
dom/html/HTMLSharedObjectElement.cpp
dom/html/HTMLSharedObjectElement.h
dom/html/HTMLSourceElement.h
dom/html/HTMLSpanElement.h
dom/html/HTMLStyleElement.h
dom/html/HTMLSummaryElement.h
dom/html/HTMLTableCaptionElement.h
dom/html/HTMLTableCellElement.h
dom/html/HTMLTableColElement.h
dom/html/HTMLTableElement.h
dom/html/HTMLTableRowElement.h
dom/html/HTMLTableSectionElement.h
dom/html/HTMLTemplateElement.h
dom/html/HTMLTextAreaElement.cpp
dom/html/HTMLTextAreaElement.h
dom/html/HTMLTimeElement.h
dom/html/HTMLTitleElement.h
dom/html/HTMLTrackElement.h
dom/html/HTMLUnknownElement.h
dom/html/HTMLVideoElement.h
dom/html/nsGenericHTMLElement.cpp
dom/html/nsGenericHTMLElement.h
dom/html/nsGenericHTMLFrameElement.cpp
dom/html/nsGenericHTMLFrameElement.h
dom/html/nsHTMLDocument.cpp
dom/html/nsHTMLDocument.h
dom/mathml/nsMathMLElement.h
dom/svg/SVGAElement.h
dom/svg/SVGAnimateElement.h
dom/svg/SVGAnimateMotionElement.h
dom/svg/SVGAnimateTransformElement.h
dom/svg/SVGAnimationElement.h
dom/svg/SVGCircleElement.h
dom/svg/SVGClipPathElement.h
dom/svg/SVGComponentTransferFunctionElement.h
dom/svg/SVGDefsElement.h
dom/svg/SVGDescElement.h
dom/svg/SVGDocument.cpp
dom/svg/SVGDocument.h
dom/svg/SVGEllipseElement.h
dom/svg/SVGFEBlendElement.h
dom/svg/SVGFEColorMatrixElement.h
dom/svg/SVGFEComponentTransferElement.h
dom/svg/SVGFECompositeElement.h
dom/svg/SVGFEConvolveMatrixElement.h
dom/svg/SVGFEDiffuseLightingElement.h
dom/svg/SVGFEDisplacementMapElement.h
dom/svg/SVGFEDistantLightElement.h
dom/svg/SVGFEDropShadowElement.h
dom/svg/SVGFEFloodElement.h
dom/svg/SVGFEGaussianBlurElement.h
dom/svg/SVGFEImageElement.h
dom/svg/SVGFEMergeElement.h
dom/svg/SVGFEMergeNodeElement.h
dom/svg/SVGFEMorphologyElement.h
dom/svg/SVGFEOffsetElement.h
dom/svg/SVGFEPointLightElement.h
dom/svg/SVGFESpecularLightingElement.h
dom/svg/SVGFESpotLightElement.h
dom/svg/SVGFETileElement.h
dom/svg/SVGFETurbulenceElement.h
dom/svg/SVGFilterElement.h
dom/svg/SVGForeignObjectElement.h
dom/svg/SVGGElement.h
dom/svg/SVGGradientElement.h
dom/svg/SVGImageElement.cpp
dom/svg/SVGImageElement.h
dom/svg/SVGLineElement.h
dom/svg/SVGMPathElement.h
dom/svg/SVGMarkerElement.h
dom/svg/SVGMaskElement.h
dom/svg/SVGMetadataElement.h
dom/svg/SVGPathElement.h
dom/svg/SVGPatternElement.h
dom/svg/SVGPolygonElement.h
dom/svg/SVGPolylineElement.h
dom/svg/SVGRectElement.h
dom/svg/SVGSVGElement.cpp
dom/svg/SVGSVGElement.h
dom/svg/SVGScriptElement.cpp
dom/svg/SVGScriptElement.h
dom/svg/SVGSetElement.h
dom/svg/SVGStopElement.h
dom/svg/SVGStyleElement.h
dom/svg/SVGSwitchElement.h
dom/svg/SVGSymbolElement.h
dom/svg/SVGTSpanElement.h
dom/svg/SVGTextElement.h
dom/svg/SVGTextPathElement.h
dom/svg/SVGTitleElement.h
dom/svg/SVGTransformableElement.h
dom/svg/SVGUseElement.cpp
dom/svg/SVGUseElement.h
dom/svg/SVGViewElement.h
dom/svg/nsSVGElement.h
dom/svg/nsSVGFilters.h
dom/xbl/XBLChildrenElement.h
dom/xml/XMLDocument.cpp
dom/xml/XMLDocument.h
dom/xml/nsXMLElement.h
dom/xul/XULDocument.cpp
dom/xul/XULDocument.h
dom/xul/nsXULElement.cpp
dom/xul/nsXULElement.h
--- a/dom/base/Attr.cpp
+++ b/dom/base/Attr.cpp
@@ -246,17 +246,18 @@ void
 Attr::SetNodeValueInternal(const nsAString& aNodeValue, ErrorResult& aError)
 {
   OwnerDoc()->WarnOnceAbout(nsIDocument::eNodeValue);
 
   aError = SetValue(aNodeValue);
 }
 
 nsresult
-Attr::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const
+Attr::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+            bool aPreallocateChildren) const
 {
   nsAutoString value;
   const_cast<Attr*>(this)->GetValue(value);
 
   RefPtr<mozilla::dom::NodeInfo> ni = aNodeInfo;
   *aResult = new Attr(nullptr, ni.forget(), value);
   if (!*aResult) {
     return NS_ERROR_OUT_OF_MEMORY;
--- a/dom/base/Attr.h
+++ b/dom/base/Attr.h
@@ -65,17 +65,18 @@ public:
   virtual bool IsNodeOfType(uint32_t aFlags) const override;
   virtual uint32_t GetChildCount() const override;
   virtual nsIContent *GetChildAt(uint32_t aIndex) const override;
   virtual nsIContent * const * GetChildArray(uint32_t* aChildCount) const override;
   virtual int32_t IndexOf(const nsINode* aPossibleChild) const override;
   virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex,
                                  bool aNotify) override;
   virtual void RemoveChildAt(uint32_t aIndex, bool aNotify) override;
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
   virtual already_AddRefed<nsIURI> GetBaseURI(bool aTryUseXHRDocBaseURI = false) const override;
 
   static void Initialize();
   static void Shutdown();
 
   NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Attr,
                                                                    nsIAttribute)
 
--- a/dom/base/DocumentFragment.h
+++ b/dom/base/DocumentFragment.h
@@ -139,17 +139,18 @@ public:
   virtual void DumpContent(FILE* out, int32_t aIndent, bool aDumpAll) const override;
 #endif
 
 protected:
   virtual ~DocumentFragment()
   {
   }
 
-  nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                 bool aPreallocateChildren) const override;
   nsIContent* mHost; // Weak
 };
 
 } // namespace dom
 } // namespace mozilla
 
 
 #endif // mozilla_dom_DocumentFragment_h__
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -1648,50 +1648,52 @@ inline void nsINode::UnsetRestyleFlagsIf
 }
 
 /**
  * Macros to implement Clone(). _elementName is the class for which to implement
  * Clone.
  */
 #define NS_IMPL_ELEMENT_CLONE(_elementName)                                 \
 nsresult                                                                    \
-_elementName::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const \
+_elementName::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,   \
+                    bool aPreallocateChildren) const                        \
 {                                                                           \
   *aResult = nullptr;                                                       \
   already_AddRefed<mozilla::dom::NodeInfo> ni =                             \
     RefPtr<mozilla::dom::NodeInfo>(aNodeInfo).forget();                   \
   _elementName *it = new _elementName(ni);                                  \
   if (!it) {                                                                \
     return NS_ERROR_OUT_OF_MEMORY;                                          \
   }                                                                         \
                                                                             \
   nsCOMPtr<nsINode> kungFuDeathGrip = it;                                   \
-  nsresult rv = const_cast<_elementName*>(this)->CopyInnerTo(it);           \
+  nsresult rv = const_cast<_elementName*>(this)->CopyInnerTo(it, aPreallocateChildren); \
   if (NS_SUCCEEDED(rv)) {                                                   \
     kungFuDeathGrip.swap(*aResult);                                         \
   }                                                                         \
                                                                             \
   return rv;                                                                \
 }
 
 #define NS_IMPL_ELEMENT_CLONE_WITH_INIT(_elementName)                       \
 nsresult                                                                    \
-_elementName::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const \
+_elementName::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,   \
+                    bool aPreallocateChildren) const                        \
 {                                                                           \
   *aResult = nullptr;                                                       \
   already_AddRefed<mozilla::dom::NodeInfo> ni =                             \
     RefPtr<mozilla::dom::NodeInfo>(aNodeInfo).forget();                   \
   _elementName *it = new _elementName(ni);                                  \
   if (!it) {                                                                \
     return NS_ERROR_OUT_OF_MEMORY;                                          \
   }                                                                         \
                                                                             \
   nsCOMPtr<nsINode> kungFuDeathGrip = it;                                   \
   nsresult rv = it->Init();                                                 \
-  nsresult rv2 = const_cast<_elementName*>(this)->CopyInnerTo(it);          \
+  nsresult rv2 = const_cast<_elementName*>(this)->CopyInnerTo(it, aPreallocateChildren); \
   if (NS_FAILED(rv2)) {                                                     \
     rv = rv2;                                                               \
   }                                                                         \
   if (NS_SUCCEEDED(rv)) {                                                   \
     kungFuDeathGrip.swap(*aResult);                                         \
   }                                                                         \
                                                                             \
   return rv;                                                                \
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -2053,25 +2053,30 @@ NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(FragmentOrElement)
 NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(FragmentOrElement,
                                                    nsNodeUtils::LastRelease(this))
 
 //----------------------------------------------------------------------
 
 nsresult
-FragmentOrElement::CopyInnerTo(FragmentOrElement* aDst)
+FragmentOrElement::CopyInnerTo(FragmentOrElement* aDst,
+                               bool aPreallocateChildren)
 {
+  nsresult rv = aDst->mAttrsAndChildren.EnsureCapacityToClone(mAttrsAndChildren,
+                                                              aPreallocateChildren);
+  NS_ENSURE_SUCCESS(rv, rv);
+
   uint32_t i, count = mAttrsAndChildren.AttrCount();
   for (i = 0; i < count; ++i) {
     const nsAttrName* name = mAttrsAndChildren.AttrNameAt(i);
     const nsAttrValue* value = mAttrsAndChildren.AttrAt(i);
     nsAutoString valStr;
     value->ToString(valStr);
-    nsresult rv = aDst->SetAttr(name->NamespaceID(), name->LocalName(),
+    rv = aDst->SetAttr(name->NamespaceID(), name->LocalName(),
                                 name->GetPrefix(), valStr, false);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
 const nsTextFragment*
--- a/dom/base/FragmentOrElement.h
+++ b/dom/base/FragmentOrElement.h
@@ -231,17 +231,17 @@ public:
   static bool IsHTMLVoid(nsIAtom* aLocalName);
 protected:
   virtual ~FragmentOrElement();
 
   /**
    * Copy attributes and state to another element
    * @param aDest the object to copy to
    */
-  nsresult CopyInnerTo(FragmentOrElement* aDest);
+  nsresult CopyInnerTo(FragmentOrElement* aDest, bool aPreallocateChildren);
 
 public:
   // Because of a bug in MS C++ compiler nsDOMSlots must be declared public,
   // otherwise nsXULElement::nsXULSlots doesn't compile.
   /**
    * There are a set of DOM- and scripting-specific instance variables
    * that may only be instantiated when a content object is accessed
    * through the DOM. Rather than burn actual slots in the content
--- a/dom/base/ShadowRoot.cpp
+++ b/dom/base/ShadowRoot.cpp
@@ -705,17 +705,18 @@ ShadowRoot::ContentRemoved(nsIDocument* 
   // Watch for node that is removed from the pool because
   // it may need to be removed from an insertion point.
   if (IsPooledNode(aChild, aContainer, mPoolHost)) {
     RemoveDistributedNode(aChild);
   }
 }
 
 nsresult
-ShadowRoot::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const
+ShadowRoot::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                  bool aPreallocateChildren) const
 {
   *aResult = nullptr;
   return NS_ERROR_DOM_DATA_CLONE_ERR;
 }
 
 void
 ShadowRoot::DestroyContent()
 {
--- a/dom/base/ShadowRoot.h
+++ b/dom/base/ShadowRoot.h
@@ -181,17 +181,18 @@ protected:
   bool mInsertionPointChanged;
 
   // Flag to indicate whether the descendants of this shadow root are part of the
   // composed document. Ideally, we would use a node flag on nodes to
   // mark whether it is in the composed document, but we have run out of flags
   // so instead we track it here.
   bool mIsComposedDocParticipant;
 
-  nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                 bool aPreallocateChildren) const override;
 };
 
 class ShadowRootStyleSheetList : public StyleSheetList
 {
 public:
   explicit ShadowRootStyleSheetList(ShadowRoot* aShadowRoot);
 
   NS_DECL_ISUPPORTS_INHERITED
--- a/dom/base/nsAttrAndChildArray.cpp
+++ b/dom/base/nsAttrAndChildArray.cpp
@@ -789,16 +789,54 @@ nsAttrAndChildArray::MakeMappedUnique(ns
 }
 
 const nsMappedAttributes*
 nsAttrAndChildArray::GetMapped() const
 {
   return mImpl ? mImpl->mMappedAttrs : nullptr;
 }
 
+nsresult nsAttrAndChildArray::EnsureCapacityToClone(const nsAttrAndChildArray& aOther,
+                                                    bool aAllocateChildren)
+{
+  NS_PRECONDITION(!mImpl, "nsAttrAndChildArray::EnsureCapacityToClone requires the array be empty when called");
+
+  uint32_t attrCount = aOther.NonMappedAttrCount();
+  uint32_t childCount = 0;
+  if (aAllocateChildren) {
+    childCount = aOther.ChildCount();
+  }
+
+  if (attrCount == 0 && childCount == 0) {
+    return NS_OK;
+  }
+
+  // No need to use a CheckedUint32 because we are cloning. We know that we
+  // have already allocated an nsAttrAndChildArray of this size.
+  uint32_t size = attrCount;
+  size *= ATTRSIZE;
+  size += childCount;
+  uint32_t totalSize = size;
+  totalSize += NS_IMPL_EXTRA_SIZE;
+
+  mImpl = static_cast<Impl*>(malloc(totalSize * sizeof(void*)));
+  NS_ENSURE_TRUE(mImpl, NS_ERROR_OUT_OF_MEMORY);
+
+  mImpl->mMappedAttrs = nullptr;
+  mImpl->mBufferSize = size;
+
+  // The array is now the right size, but we should reserve the correct
+  // number of slots for attributes so that children don't get written into
+  // that part of the array (which will then need to be moved later).
+  memset(static_cast<void*>(mImpl->mBuffer), 0, sizeof(InternalAttr) * attrCount);
+  SetAttrSlotAndChildCount(attrCount, 0);
+
+  return NS_OK;
+}
+
 bool
 nsAttrAndChildArray::GrowBy(uint32_t aGrowSize)
 {
   CheckedUint32 size = 0;
   if (mImpl) {
     size += mImpl->mBufferSize;
     size += NS_IMPL_EXTRA_SIZE;
     if (!size.isValid()) {
--- a/dom/base/nsAttrAndChildArray.h
+++ b/dom/base/nsAttrAndChildArray.h
@@ -138,16 +138,23 @@ public:
 
   // Force this to have mapped attributes, even if those attributes are empty.
   nsresult ForceMapped(nsMappedAttributeElement* aContent, nsIDocument* aDocument);
 
   // Clear the servo declaration block on the mapped attributes, if any
   // Will assert off main thread
   void ClearMappedServoStyle();
 
+  // Increases capacity (if necessary) to have enough space to accomodate the
+  // unmapped attributes and children of |aOther|. If |aAllocateChildren| is not
+  // true, only enough space for unmapped attributes will be reserved.
+  // It is REQUIRED that this function be called ONLY when the array is empty.
+  nsresult EnsureCapacityToClone(const nsAttrAndChildArray& aOther,
+                                 bool aAllocateChildren);
+
 private:
   nsAttrAndChildArray(const nsAttrAndChildArray& aOther) = delete;
   nsAttrAndChildArray& operator=(const nsAttrAndChildArray& aOther) = delete;
 
   void Clear();
 
   uint32_t NonMappedAttrCount() const;
   uint32_t MappedAttrCount() const;
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -9313,17 +9313,17 @@ nsDocument::RefreshLinkHrefs()
   // Reset all of our styled links.
   nsAutoScriptBlocker scriptBlocker;
   for (LinkArray::size_type i = 0; i < linksToNotify.Length(); i++) {
     linksToNotify[i]->ResetLinkState(true, linksToNotify[i]->ElementHasHref());
   }
 }
 
 nsresult
-nsDocument::CloneDocHelper(nsDocument* clone) const
+nsDocument::CloneDocHelper(nsDocument* clone, bool aPreallocateChildren) const
 {
   clone->mIsStaticDocument = mCreatingStaticClone;
 
   // Init document
   nsresult rv = clone->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (mCreatingStaticClone) {
@@ -9390,16 +9390,21 @@ nsDocument::CloneDocHelper(nsDocument* c
   clone->mContentLanguage = mContentLanguage;
   clone->SetContentTypeInternal(GetContentTypeInternal());
   clone->mSecurityInfo = mSecurityInfo;
 
   // State from nsDocument
   clone->mType = mType;
   clone->mXMLDeclarationBits = mXMLDeclarationBits;
   clone->mBaseTarget = mBaseTarget;
+
+  // Preallocate attributes and child arrays
+  rv = clone->mChildren.EnsureCapacityToClone(mChildren, aPreallocateChildren);
+  NS_ENSURE_SUCCESS(rv, rv);
+
   return NS_OK;
 }
 
 void
 nsDocument::SetReadyStateInternal(ReadyState rs)
 {
   mReadyState = rs;
   if (rs == READYSTATE_UNINITIALIZED) {
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -807,17 +807,18 @@ public:
   virtual bool IsNodeOfType(uint32_t aFlags) const override;
   virtual nsIContent *GetChildAt(uint32_t aIndex) const override;
   virtual nsIContent * const * GetChildArray(uint32_t* aChildCount) const override;
   virtual int32_t IndexOf(const nsINode* aPossibleChild) const override;
   virtual uint32_t GetChildCount() const override;
   virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex,
                                  bool aNotify) override;
   virtual void RemoveChildAt(uint32_t aIndex, bool aNotify) override;
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override
   {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   // nsIRadioGroupContainer
   NS_IMETHOD WalkRadioGroup(const nsAString& aName,
                             nsIRadioVisitor* aVisitor,
                             bool aFlushContent) override;
@@ -1006,17 +1007,17 @@ public:
   }
 
   void SetLoadedAsData(bool aLoadedAsData) { mLoadedAsData = aLoadedAsData; }
   void SetLoadedAsInteractiveData(bool aLoadedAsInteractiveData)
   {
     mLoadedAsInteractiveData = aLoadedAsInteractiveData;
   }
 
-  nsresult CloneDocHelper(nsDocument* clone) const;
+  nsresult CloneDocHelper(nsDocument* clone, bool aPreallocateChildren) const;
 
   void MaybeInitializeFinalizeFrameLoaders();
 
   void MaybeEndOutermostXBLUpdate();
 
   virtual void PreloadPictureOpened() override;
   virtual void PreloadPictureClosed() override;
 
--- a/dom/base/nsGenericDOMDataNode.h
+++ b/dom/base/nsGenericDOMDataNode.h
@@ -162,17 +162,18 @@ public:
   virtual bool IsNodeOfType(uint32_t aFlags) const override;
   virtual bool IsLink(nsIURI** aURI) const override;
 
   NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
   virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
                                               int32_t aModType) const;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override
   {
     nsCOMPtr<nsINode> result = CloneDataNode(aNodeInfo, true);
     result.forget(aResult);
 
     if (!*aResult) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
--- a/dom/base/nsINode.h
+++ b/dom/base/nsINode.h
@@ -1079,18 +1079,21 @@ public:
   /**
    * Clones this node. This needs to be overriden by all node classes. aNodeInfo
    * should be identical to this node's nodeInfo, except for the document which
    * may be different. When cloning an element, all attributes of the element
    * will be cloned. The children of the node will not be cloned.
    *
    * @param aNodeInfo the nodeinfo to use for the clone
    * @param aResult the clone
+   * @param aPreallocateChildren If true, the array of children will be
+   *                             preallocated in preparation for a deep copy.
    */
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const = 0;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const = 0;
 
   // This class can be extended by subclasses that wish to store more
   // information in the slots.
   class nsSlots
   {
   public:
     nsSlots();
 
--- a/dom/base/nsNodeUtils.cpp
+++ b/dom/base/nsNodeUtils.cpp
@@ -468,17 +468,17 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNod
 
     nodeInfo = newNodeInfo;
   }
 
   Element *elem = aNode->IsElement() ? aNode->AsElement() : nullptr;
 
   nsCOMPtr<nsINode> clone;
   if (aClone) {
-    rv = aNode->Clone(nodeInfo, getter_AddRefs(clone));
+    rv = aNode->Clone(nodeInfo, getter_AddRefs(clone), aDeep);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (clone->IsElement()) {
       // The cloned node may be a custom element that may require
       // enqueing created callback and prototype swizzling.
       Element* elem = clone->AsElement();
       if (nsContentUtils::IsCustomElementName(nodeInfo->NameAtom())) {
         nsContentUtils::SetupCustomElement(elem);
--- a/dom/html/HTMLAnchorElement.h
+++ b/dom/html/HTMLAnchorElement.h
@@ -76,17 +76,18 @@ public:
                            bool aNotify) override;
   virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
                              bool aNotify) override;
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult) override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   virtual EventStates IntrinsicState() const override;
 
   virtual void OnDNSPrefetchDeferred() override;
   virtual void OnDNSPrefetchRequested() override;
   virtual bool HasDeferredDNSPrefetchRequest() override;
 
   // WebIDL API
--- a/dom/html/HTMLAreaElement.h
+++ b/dom/html/HTMLAreaElement.h
@@ -62,17 +62,18 @@ public:
     return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
   }
   virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                            nsIAtom* aPrefix, const nsAString& aValue,
                            bool aNotify) override;
   virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
                              bool aNotify) override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
+                         bool aPreallocateChildren) const override;
 
   virtual EventStates IntrinsicState() const override;
 
   // WebIDL
 
   // The XPCOM GetAlt is OK for us
   void SetAlt(const nsAString& aAlt, ErrorResult& aError)
   {
--- a/dom/html/HTMLAudioElement.h
+++ b/dom/html/HTMLAudioElement.h
@@ -24,17 +24,18 @@ public:
   explicit HTMLAudioElement(already_AddRefed<NodeInfo>& aNodeInfo);
 
   // Element
   virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const override;
 
   // nsIDOMHTMLMediaElement
   using HTMLMediaElement::GetPaused;
 
-  virtual nsresult Clone(NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
   virtual nsresult SetAcceptHeader(nsIHttpChannel* aChannel) override;
 
   virtual nsIDOMNode* AsDOMNode() override { return this; }
 
   // WebIDL
 
   static already_AddRefed<HTMLAudioElement>
   Audio(const GlobalObject& aGlobal,
--- a/dom/html/HTMLBRElement.h
+++ b/dom/html/HTMLBRElement.h
@@ -20,17 +20,18 @@ public:
   explicit HTMLBRElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   bool Clear()
   {
     return GetBoolAttr(nsGkAtoms::clear);
   }
   void SetClear(const nsAString& aClear, ErrorResult& aError)
   {
     return SetHTMLAttr(nsGkAtoms::clear, aClear, aError);
--- a/dom/html/HTMLBodyElement.h
+++ b/dom/html/HTMLBodyElement.h
@@ -101,17 +101,18 @@ public:
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsIAtom* aAttribute,
                               const nsAString& aValue,
                               nsAttrValue& aResult) override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
   virtual already_AddRefed<nsIEditor> GetAssociatedEditor() override;
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   virtual bool IsEventAttributeName(nsIAtom* aName) override;
 
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   /**
--- a/dom/html/HTMLButtonElement.h
+++ b/dom/html/HTMLButtonElement.h
@@ -57,17 +57,18 @@ public:
 
   // nsIDOMEventTarget
   virtual nsresult GetEventTargetParent(
                      EventChainPreVisitor& aVisitor) override;
   virtual nsresult PostHandleEvent(
                      EventChainPostVisitor& aVisitor) override;
 
   // nsINode
-  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
+                         bool aPreallocateChildren) const override;
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   // nsIContent
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
--- a/dom/html/HTMLCanvasElement.cpp
+++ b/dom/html/HTMLCanvasElement.cpp
@@ -556,19 +556,20 @@ HTMLCanvasElement::IsPrintCallbackDone()
 
 HTMLCanvasElement*
 HTMLCanvasElement::GetOriginalCanvas()
 {
   return mOriginalCanvas ? mOriginalCanvas.get() : this;
 }
 
 nsresult
-HTMLCanvasElement::CopyInnerTo(Element* aDest)
+HTMLCanvasElement::CopyInnerTo(Element* aDest,
+                               bool aPreallocateChildren)
 {
-  nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest);
+  nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest, aPreallocateChildren);
   NS_ENSURE_SUCCESS(rv, rv);
   if (aDest->OwnerDoc()->IsStaticDocument()) {
     HTMLCanvasElement* dest = static_cast<HTMLCanvasElement*>(aDest);
     dest->mOriginalCanvas = this;
 
     nsCOMPtr<nsISupports> cxt;
     dest->GetContext(NS_LITERAL_STRING("2d"), getter_AddRefs(cxt));
     RefPtr<CanvasRenderingContext2D> context2d =
--- a/dom/html/HTMLCanvasElement.h
+++ b/dom/html/HTMLCanvasElement.h
@@ -302,18 +302,20 @@ public:
   }
   virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                            nsIAtom* aPrefix, const nsAString& aValue,
                            bool aNotify) override;
 
   virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                              bool aNotify) override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
-  nsresult CopyInnerTo(mozilla::dom::Element* aDest);
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
+  nsresult CopyInnerTo(mozilla::dom::Element* aDest,
+                       bool aPreallocateChildren);
 
   virtual nsresult GetEventTargetParent(
                      mozilla::EventChainPreVisitor& aVisitor) override;
 
   /*
    * Helpers called by various users of Canvas
    */
 
--- a/dom/html/HTMLContentElement.h
+++ b/dom/html/HTMLContentElement.h
@@ -35,17 +35,18 @@ public:
       return static_cast<HTMLContentElement*>(aContent);
     }
 
     return nullptr;
   }
 
   virtual bool IsHTMLContentElement() const override { return true; }
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   virtual nsIDOMNode* AsDOMNode() override { return this; }
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
 
   virtual void UnbindFromTree(bool aDeep = true,
--- a/dom/html/HTMLDataElement.h
+++ b/dom/html/HTMLDataElement.h
@@ -26,17 +26,18 @@ public:
     GetHTMLAttr(nsGkAtoms::value, aValue);
   }
 
   void SetValue(const nsAString& aValue, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::value, aValue, aError);
   }
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
+                         bool aPreallocateChildren) const override;
 
 protected:
   virtual ~HTMLDataElement();
 
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 };
 
 } // namespace dom
--- a/dom/html/HTMLDataListElement.h
+++ b/dom/html/HTMLDataListElement.h
@@ -29,17 +29,18 @@ public:
     if (!mOptions) {
       mOptions = new nsContentList(this, MatchOptions, nullptr, nullptr, true);
     }
 
     return mOptions;
   }
 
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // This function is used to generate the nsContentList (option elements).
   static bool MatchOptions(Element* aElement, int32_t aNamespaceID,
                            nsIAtom* aAtom, void* aData);
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLDataListElement,
                                            nsGenericHTMLElement)
 protected:
--- a/dom/html/HTMLDetailsElement.h
+++ b/dom/html/HTMLDetailsElement.h
@@ -27,17 +27,18 @@ public:
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
 
   NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLDetailsElement, details)
 
   nsIContent* GetFirstSummary() const;
 
-  nsresult Clone(NodeInfo* aNodeInfo, nsINode** aResult) const override;
+  nsresult Clone(NodeInfo* aNodeInfo, nsINode** aResult,
+                 bool aPreallocateChildren) const override;
 
   nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
                                       int32_t aModType) const override;
 
   nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                          const nsAttrValueOrString* aValue,
                          bool aNotify) override;
 
--- a/dom/html/HTMLDialogElement.h
+++ b/dom/html/HTMLDialogElement.h
@@ -19,17 +19,18 @@ class HTMLDialogElement final : public n
 {
 public:
   explicit HTMLDialogElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo) : nsGenericHTMLElement(aNodeInfo)
   {
   }
 
   NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLDialogElement, dialog)
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
+                         bool aPreallocateChildren) const override;
 
   static bool IsDialogEnabled();
 
   bool Open() const { return GetBoolAttr(nsGkAtoms::open); }
   void SetOpen(bool aOpen, ErrorResult& aError)
   {
     SetHTMLBoolAttr(nsGkAtoms::open, aOpen, aError);
   }
--- a/dom/html/HTMLDivElement.h
+++ b/dom/html/HTMLDivElement.h
@@ -30,17 +30,18 @@ public:
   }
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsIAtom* aAttribute,
                               const nsAString& aValue,
                               nsAttrValue& aResult) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
 protected:
   virtual ~HTMLDivElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
--- a/dom/html/HTMLElement.cpp
+++ b/dom/html/HTMLElement.cpp
@@ -13,17 +13,18 @@ namespace dom {
 
 class HTMLElement final : public nsGenericHTMLElement
 {
 public:
   explicit HTMLElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
   virtual ~HTMLElement();
 
   virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo,
-                         nsINode** aResult) const override;
+                         nsINode** aResult,
+                         bool aPreallocateChildren) const override;
 
 protected:
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 };
 
 HTMLElement::HTMLElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo)
 {
--- a/dom/html/HTMLFieldSetElement.h
+++ b/dom/html/HTMLFieldSetElement.h
@@ -48,17 +48,18 @@ public:
   virtual nsresult InsertChildAt(nsIContent* aChild, uint32_t aIndex,
                                      bool aNotify) override;
   virtual void RemoveChildAt(uint32_t aIndex, bool aNotify) override;
 
   // nsIFormControl
   NS_IMETHOD Reset() override;
   NS_IMETHOD SubmitNamesValues(HTMLFormSubmission* aFormSubmission) override;
   virtual bool IsDisabledForEvents(EventMessage aMessage) override;
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   const nsIContent* GetFirstLegend() const { return mFirstLegend; }
 
   void AddElement(nsGenericHTMLFormElement* aElement);
 
   void RemoveElement(nsGenericHTMLFormElement* aElement);
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLFieldSetElement,
--- a/dom/html/HTMLFontElement.h
+++ b/dom/html/HTMLFontElement.h
@@ -46,17 +46,18 @@ public:
   }
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
 protected:
   virtual ~HTMLFontElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
--- a/dom/html/HTMLFormElement.h
+++ b/dom/html/HTMLFormElement.h
@@ -117,17 +117,18 @@ public:
                                 const nsAttrValue* aValue, bool aNotify) override;
 
   /**
    * Forget all information about the current submission (and the fact that we
    * are currently submitting at all).
    */
   void ForgetCurrentSubmission();
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLFormElement,
                                            nsGenericHTMLElement)
 
   /**
    * Remove an element from this form's list of elements
    *
    * @param aElement the element to remove
--- a/dom/html/HTMLFrameElement.h
+++ b/dom/html/HTMLFrameElement.h
@@ -30,17 +30,18 @@ public:
   // nsIDOMHTMLFrameElement
   NS_DECL_NSIDOMHTMLFRAMEELEMENT
 
   // nsIContent
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsIAtom* aAttribute,
                               const nsAString& aValue,
                               nsAttrValue& aResult) override;
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL API
   // The XPCOM GetFrameBorder is OK for us
   void SetFrameBorder(const nsAString& aFrameBorder, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::frameborder, aFrameBorder, aError);
   }
 
--- a/dom/html/HTMLFrameSetElement.h
+++ b/dom/html/HTMLFrameSetElement.h
@@ -131,17 +131,18 @@ public:
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult) override;
   virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
                                               int32_t aModType) const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
 protected:
   virtual ~HTMLFrameSetElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   nsresult ParseRowCol(const nsAString& aValue,
--- a/dom/html/HTMLHRElement.h
+++ b/dom/html/HTMLHRElement.h
@@ -30,17 +30,18 @@ public:
   NS_DECL_NSIDOMHTMLHRELEMENT
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsIAtom* aAttribute,
                               const nsAString& aValue,
                               nsAttrValue& aResult) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL API
   void SetAlign(const nsAString& aAlign, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::align, aAlign, aError);
   }
 
   // The XPCOM GetColor is OK for us
--- a/dom/html/HTMLHeadingElement.h
+++ b/dom/html/HTMLHeadingElement.h
@@ -22,17 +22,18 @@ public:
   }
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsIAtom* aAttribute,
                               const nsAString& aValue,
                               nsAttrValue& aResult) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
   nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   void SetAlign(const nsAString& aAlign, ErrorResult& aError)
   {
     return SetHTMLAttr(nsGkAtoms::align, aAlign, aError);
   }
   void GetAlign(DOMString& aAlign) const
   {
     return GetHTMLAttr(nsGkAtoms::align, aAlign);
--- a/dom/html/HTMLIFrameElement.h
+++ b/dom/html/HTMLIFrameElement.h
@@ -39,17 +39,18 @@ public:
   // nsIContent
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                    const nsAString& aValue, bool aNotify)
   {
     return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
   }
   virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                            nsIAtom* aPrefix, const nsAString& aValue,
--- a/dom/html/HTMLImageElement.cpp
+++ b/dom/html/HTMLImageElement.cpp
@@ -805,25 +805,25 @@ HTMLImageElement::NaturalWidth()
 NS_IMETHODIMP
 HTMLImageElement::GetNaturalWidth(uint32_t* aNaturalWidth)
 {
   *aNaturalWidth = NaturalWidth();
   return NS_OK;
 }
 
 nsresult
-HTMLImageElement::CopyInnerTo(Element* aDest)
+HTMLImageElement::CopyInnerTo(Element* aDest, bool aPreallocateChildren)
 {
   bool destIsStatic = aDest->OwnerDoc()->IsStaticDocument();
   auto dest = static_cast<HTMLImageElement*>(aDest);
   if (destIsStatic) {
     CreateStaticImageClone(dest);
   }
 
-  nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest);
+  nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest, aPreallocateChildren);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   if (!destIsStatic) {
     // In SetAttr (called from nsGenericHTMLElement::CopyInnerTo), dest skipped
     // doing the image load because we passed in false for aNotify.  But we
     // really do want it to do the load, so set it up to happen once the cloning
--- a/dom/html/HTMLImageElement.h
+++ b/dom/html/HTMLImageElement.h
@@ -87,21 +87,22 @@ public:
                            bool aNotify) override;
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
 
   virtual EventStates IntrinsicState() const override;
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   virtual void NodeInfoChanged(nsIDocument* aOldDoc) override;
 
-  nsresult CopyInnerTo(Element* aDest);
+  nsresult CopyInnerTo(Element* aDest, bool aPreallocateChildren);
 
   void MaybeLoadImage();
 
   bool IsMap()
   {
     return GetBoolAttr(nsGkAtoms::ismap);
   }
   void SetIsMap(bool aIsMap, ErrorResult& aError)
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -1280,25 +1280,26 @@ NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION
 NS_INTERFACE_TABLE_TAIL_INHERITING(nsGenericHTMLFormElementWithState)
 
 // nsIConstraintValidation
 NS_IMPL_NSICONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY(HTMLInputElement)
 
 // nsIDOMNode
 
 nsresult
-HTMLInputElement::Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const
+HTMLInputElement::Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
+                        bool aPreallocateArrays) const
 {
   *aResult = nullptr;
 
   already_AddRefed<mozilla::dom::NodeInfo> ni = RefPtr<mozilla::dom::NodeInfo>(aNodeInfo).forget();
   RefPtr<HTMLInputElement> it = new HTMLInputElement(ni, NOT_FROM_PARSER,
                                                      FromClone::yes);
 
-  nsresult rv = const_cast<HTMLInputElement*>(this)->CopyInnerTo(it);
+  nsresult rv = const_cast<HTMLInputElement*>(this)->CopyInnerTo(it, aPreallocateArrays);
   NS_ENSURE_SUCCESS(rv, rv);
 
   switch (GetValueMode()) {
     case VALUE_MODE_VALUE:
       if (mValueChanged) {
         // We don't have our default value anymore.  Set our value on
         // the clone.
         nsAutoString value;
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -280,17 +280,18 @@ public:
    * Helper function returning the currently selected button in the radio group.
    * Returning null if the element is not a button or if there is no selectied
    * button in the group.
    *
    * @return the selected button (or null).
    */
   already_AddRefed<nsIDOMHTMLInputElement> GetSelectedRadioButton() const;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLInputElement,
                                            nsGenericHTMLFormElementWithState)
 
   static UploadLastDir* gUploadLastDir;
   // create and destroy the static UploadLastDir object for remembering
   // which directory was last used on a site-by-site basis
   static void InitUploadLastDir();
--- a/dom/html/HTMLLIElement.h
+++ b/dom/html/HTMLLIElement.h
@@ -31,17 +31,18 @@ public:
   NS_DECL_NSIDOMHTMLLIELEMENT
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL API
   void GetType(DOMString& aType)
   {
     GetHTMLAttr(nsGkAtoms::type, aType);
   }
   void SetType(const nsAString& aType, mozilla::ErrorResult& rv)
   {
--- a/dom/html/HTMLLabelElement.h
+++ b/dom/html/HTMLLabelElement.h
@@ -61,17 +61,18 @@ public:
 
   virtual bool IsDisabled() const override { return false; }
 
   // nsIContent
   virtual nsresult PostHandleEvent(
                      EventChainPostVisitor& aVisitor) override;
   virtual bool PerformAccesskey(bool aKeyCausesActivation,
                                 bool aIsTrustedEvent) override;
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   nsGenericHTMLElement* GetLabeledElement() const;
 protected:
   virtual ~HTMLLabelElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   nsGenericHTMLElement* GetFirstLabelableDescendant() const;
--- a/dom/html/HTMLLegendElement.h
+++ b/dom/html/HTMLLegendElement.h
@@ -48,17 +48,18 @@ public:
     return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
   }
   virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                            nsIAtom* aPrefix, const nsAString& aValue,
                            bool aNotify) override;
   virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
                              bool aNotify) override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
+                         bool aPreallocateChildren) const override;
 
   Element* GetFormElement() const
   {
     nsCOMPtr<nsIFormControl> fieldsetControl = do_QueryInterface(GetFieldSet());
 
     return fieldsetControl ? fieldsetControl->GetFormElement() : nullptr;
   }
 
--- a/dom/html/HTMLLinkElement.h
+++ b/dom/html/HTMLLinkElement.h
@@ -47,17 +47,18 @@ public:
 
   // nsIDOMEventTarget
   virtual nsresult GetEventTargetParent(
                      EventChainPreVisitor& aVisitor) override;
   virtual nsresult PostHandleEvent(
                      EventChainPostVisitor& aVisitor) override;
 
   // nsINode
-  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
+                         bool aPreallocateChildren) const override;
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   // nsIContent
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
--- a/dom/html/HTMLMapElement.h
+++ b/dom/html/HTMLMapElement.h
@@ -24,17 +24,18 @@ public:
   explicit HTMLMapElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMHTMLMapElement
   NS_DECL_NSIDOMHTMLMAPELEMENT
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(HTMLMapElement,
                                                      nsGenericHTMLElement)
 
   // XPCOM GetName is fine.
   void SetName(const nsAString& aName, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::name, aName, aError);
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -6371,19 +6371,19 @@ already_AddRefed<nsILoadGroup> HTMLMedia
 {
   if (!OwnerDoc()->IsActive()) {
     NS_WARNING("Load group requested for media element in inactive document.");
   }
   return OwnerDoc()->GetDocumentLoadGroup();
 }
 
 nsresult
-HTMLMediaElement::CopyInnerTo(Element* aDest)
-{
-  nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest);
+HTMLMediaElement::CopyInnerTo(Element* aDest, bool aPreallocateChildren)
+{
+  nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest, aPreallocateChildren);
   NS_ENSURE_SUCCESS(rv, rv);
   if (aDest->OwnerDoc()->IsStaticDocument()) {
     HTMLMediaElement* dest = static_cast<HTMLMediaElement*>(aDest);
     dest->SetMediaInfo(mMediaInfo);
   }
   return rv;
 }
 
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -380,17 +380,17 @@ public:
   already_AddRefed<nsILoadGroup> GetDocumentLoadGroup();
 
   /**
    * Returns true if the media has played or completed a seek.
    * Used by video frame to determine whether to paint the poster.
    */
   bool GetPlayedOrSeeked() const { return mHasPlayedOrSeeked; }
 
-  nsresult CopyInnerTo(Element* aDest);
+  nsresult CopyInnerTo(Element* aDest, bool aPreallocateChildren);
 
   /**
    * Sets the Accept header on the HTTP channel to the required
    * video or audio MIME types.
    */
   virtual nsresult SetAcceptHeader(nsIHttpChannel* aChannel) = 0;
 
   /**
--- a/dom/html/HTMLMenuElement.h
+++ b/dom/html/HTMLMenuElement.h
@@ -32,17 +32,18 @@ public:
 
   nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
                         const nsAttrValue* aValue, bool aNotify) override;
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult) override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   uint8_t GetType() const { return mType; }
 
   // WebIDL
 
   // The XPCOM GetType is OK for us
   void SetType(const nsAString& aType, ErrorResult& aError)
   {
--- a/dom/html/HTMLMenuItemElement.cpp
+++ b/dom/html/HTMLMenuItemElement.cpp
@@ -173,23 +173,24 @@ HTMLMenuItemElement::~HTMLMenuItemElemen
 }
 
 
 NS_IMPL_ISUPPORTS_INHERITED(HTMLMenuItemElement, nsGenericHTMLElement,
                             nsIDOMHTMLMenuItemElement)
 
 //NS_IMPL_ELEMENT_CLONE(HTMLMenuItemElement)
 nsresult
-HTMLMenuItemElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const
+HTMLMenuItemElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                           bool aPreallocateArrays) const
 {
   *aResult = nullptr;
   already_AddRefed<mozilla::dom::NodeInfo> ni = RefPtr<mozilla::dom::NodeInfo>(aNodeInfo).forget();
   RefPtr<HTMLMenuItemElement> it =
     new HTMLMenuItemElement(ni, NOT_FROM_PARSER);
-  nsresult rv = const_cast<HTMLMenuItemElement*>(this)->CopyInnerTo(it);
+  nsresult rv = const_cast<HTMLMenuItemElement*>(this)->CopyInnerTo(it, aPreallocateArrays);
   if (NS_SUCCEEDED(rv)) {
     switch (mType) {
       case CMD_TYPE_CHECKBOX:
       case CMD_TYPE_RADIO:
         if (mCheckedDirty) {
           // We no longer have our original checked state.  Set our
           // checked state on the clone.
           it->mCheckedDirty = true;
--- a/dom/html/HTMLMenuItemElement.h
+++ b/dom/html/HTMLMenuItemElement.h
@@ -47,17 +47,18 @@ public:
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult) override;
 
   virtual void DoneCreatingElement() override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   uint8_t GetType() const { return mType; }
 
   /**
    * Syntax sugar to make it easier to check for checked and checked dirty
    */
   bool IsChecked() const { return mChecked; }
   bool IsCheckedDirty() const { return mCheckedDirty; }
--- a/dom/html/HTMLMetaElement.h
+++ b/dom/html/HTMLMetaElement.h
@@ -32,17 +32,18 @@ public:
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
 
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                                 const nsAttrValue* aValue, bool aNotify) override;
 
   void CreateAndDispatchEvent(nsIDocument* aDoc, const nsAString& aEventName);
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // XPCOM GetName is fine.
   void SetName(const nsAString& aName, ErrorResult& aRv)
   {
     SetHTMLAttr(nsGkAtoms::name, aName, aRv);
   }
   // XPCOM GetHttpEquiv is fine.
   void SetHttpEquiv(const nsAString& aHttpEquiv, ErrorResult& aRv)
--- a/dom/html/HTMLMeterElement.h
+++ b/dom/html/HTMLMeterElement.h
@@ -19,17 +19,18 @@ namespace dom {
 
 class HTMLMeterElement final : public nsGenericHTMLElement
 {
 public:
   explicit HTMLMeterElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
 
   virtual EventStates IntrinsicState() const override;
 
-  nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const override;
+  nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
+                 bool aPreallocateChildren) const override;
 
   bool ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute,
                       const nsAString& aValue, nsAttrValue& aResult) override;
 
   // WebIDL
 
   /* @return the value */
   double Value() const;
--- a/dom/html/HTMLModElement.h
+++ b/dom/html/HTMLModElement.h
@@ -14,17 +14,18 @@
 namespace mozilla {
 namespace dom {
 
 class HTMLModElement final : public nsGenericHTMLElement
 {
 public:
   explicit HTMLModElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   void GetCite(nsString& aCite)
   {
     GetHTMLURIAttr(nsGkAtoms::cite, aCite);
   }
   void SetCite(const nsAString& aCite, ErrorResult& aRv)
   {
     SetHTMLAttr(nsGkAtoms::cite, aCite, aRv);
--- a/dom/html/HTMLObjectElement.cpp
+++ b/dom/html/HTMLObjectElement.cpp
@@ -565,19 +565,20 @@ HTMLObjectElement::GetCapabilities() con
 void
 HTMLObjectElement::DestroyContent()
 {
   nsObjectLoadingContent::DestroyContent();
   nsGenericHTMLFormElement::DestroyContent();
 }
 
 nsresult
-HTMLObjectElement::CopyInnerTo(Element* aDest)
+HTMLObjectElement::CopyInnerTo(Element* aDest, bool aPreallocateChildren)
 {
-  nsresult rv = nsGenericHTMLFormElement::CopyInnerTo(aDest);
+  nsresult rv = nsGenericHTMLFormElement::CopyInnerTo(aDest,
+                                                      aPreallocateChildren);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aDest->OwnerDoc()->IsStaticDocument()) {
     CreateStaticClone(static_cast<HTMLObjectElement*>(aDest));
   }
 
   return rv;
 }
--- a/dom/html/HTMLObjectElement.h
+++ b/dom/html/HTMLObjectElement.h
@@ -84,19 +84,20 @@ public:
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom *aAttribute) const override;
   virtual EventStates IntrinsicState() const override;
   virtual void DestroyContent() override;
 
   // nsObjectLoadingContent
   virtual uint32_t GetCapabilities() const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
-  nsresult CopyInnerTo(Element* aDest);
+  nsresult CopyInnerTo(Element* aDest, bool aPreallocateChildren);
 
   void StartObjectLoad() { StartObjectLoad(true, false); }
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLObjectElement,
                                            nsGenericHTMLFormElement)
 
   // Web IDL binding methods
   // XPCOM GetData is ok; note that it's a URI attribute with a weird base URI
--- a/dom/html/HTMLOptGroupElement.h
+++ b/dom/html/HTMLOptGroupElement.h
@@ -35,17 +35,18 @@ public:
   virtual void RemoveChildAt(uint32_t aIndex, bool aNotify) override;
 
   // nsIContent
   virtual nsresult GetEventTargetParent(
                      EventChainPreVisitor& aVisitor) override;
 
   virtual EventStates IntrinsicState() const override;
  
-  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
+                         bool aPreallocateChildren) const override;
 
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                                 const nsAttrValue* aValue, bool aNotify) override;
 
   virtual nsIDOMNode* AsDOMNode() override { return this; }
 
   virtual bool IsDisabled() const override {
     return HasAttr(kNameSpaceID_None, nsGkAtoms::disabled);
--- a/dom/html/HTMLOptionElement.cpp
+++ b/dom/html/HTMLOptionElement.cpp
@@ -432,19 +432,19 @@ HTMLOptionElement::Option(const GlobalOb
       }
     }
   }
 
   return option.forget();
 }
 
 nsresult
-HTMLOptionElement::CopyInnerTo(Element* aDest)
+HTMLOptionElement::CopyInnerTo(Element* aDest, bool aPreallocateChildren)
 {
-  nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest);
+  nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest, aPreallocateChildren);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aDest->OwnerDoc()->IsStaticDocument()) {
     static_cast<HTMLOptionElement*>(aDest)->SetSelected(Selected());
   }
   return NS_OK;
 }
 
--- a/dom/html/HTMLOptionElement.h
+++ b/dom/html/HTMLOptionElement.h
@@ -58,19 +58,20 @@ public:
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
 
   // nsIContent
   virtual EventStates IntrinsicState() const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
+                         bool aPreallocateChildren) const override;
 
-  nsresult CopyInnerTo(mozilla::dom::Element* aDest);
+  nsresult CopyInnerTo(mozilla::dom::Element* aDest, bool aPreallocateChildren);
 
   virtual bool IsDisabled() const override {
     return HasAttr(kNameSpaceID_None, nsGkAtoms::disabled);
   }
 
   bool Disabled() const
   {
     return GetBoolAttr(nsGkAtoms::disabled);
--- a/dom/html/HTMLOutputElement.h
+++ b/dom/html/HTMLOutputElement.h
@@ -31,17 +31,18 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIFormControl
   NS_IMETHOD Reset() override;
   NS_IMETHOD SubmitNamesValues(HTMLFormSubmission* aFormSubmission) override;
 
   virtual bool IsDisabled() const override { return false; }
 
-  nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const override;
+  nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
+                 bool aPreallocateChildren) const override;
 
   bool ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute,
                         const nsAString& aValue, nsAttrValue& aResult) override;
 
   virtual void DoneAddingChildren(bool aHaveNotified) override;
 
   EventStates IntrinsicState() const override;
 
--- a/dom/html/HTMLParagraphElement.h
+++ b/dom/html/HTMLParagraphElement.h
@@ -32,17 +32,18 @@ public:
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL API
   // The XPCOM GetAlign is fine for our purposes
   void SetAlign(const nsAString& aValue, mozilla::ErrorResult& rv)
   {
     SetHTMLAttr(nsGkAtoms::align, aValue, rv);
   }
 
--- a/dom/html/HTMLPictureElement.h
+++ b/dom/html/HTMLPictureElement.h
@@ -21,17 +21,18 @@ public:
   explicit HTMLPictureElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMHTMLPictureElement
   NS_DECL_NSIDOMHTMLPICTUREELEMENT
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
+                         bool aPreallocateChildren) const override;
   virtual void RemoveChildAt(uint32_t aIndex, bool aNotify) override;
   virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex, bool aNotify) override;
 
 protected:
   virtual ~HTMLPictureElement();
 
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 };
--- a/dom/html/HTMLPreElement.h
+++ b/dom/html/HTMLPreElement.h
@@ -33,17 +33,18 @@ public:
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL API
   int32_t Width() const
   {
     return GetIntAttr(nsGkAtoms::width, 0);
   }
   void SetWidth(int32_t aWidth, mozilla::ErrorResult& rv)
   {
--- a/dom/html/HTMLProgressElement.h
+++ b/dom/html/HTMLProgressElement.h
@@ -18,17 +18,18 @@ namespace dom {
 
 class HTMLProgressElement final : public nsGenericHTMLElement
 {
 public:
   explicit HTMLProgressElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
 
   EventStates IntrinsicState() const override;
 
-  nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const override;
+  nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
+                 bool aPreallocateChildren) const override;
 
   bool ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute,
                         const nsAString& aValue, nsAttrValue& aResult) override;
 
   // WebIDL
   double Value() const;
   void SetValue(double aValue, ErrorResult& aRv)
   {
--- a/dom/html/HTMLScriptElement.cpp
+++ b/dom/html/HTMLScriptElement.cpp
@@ -88,25 +88,26 @@ HTMLScriptElement::ParseAttribute(int32_
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 nsresult
-HTMLScriptElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const
+HTMLScriptElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const
 {
   *aResult = nullptr;
 
   already_AddRefed<mozilla::dom::NodeInfo> ni = RefPtr<mozilla::dom::NodeInfo>(aNodeInfo).forget();
   HTMLScriptElement* it = new HTMLScriptElement(ni, NOT_FROM_PARSER);
 
   nsCOMPtr<nsINode> kungFuDeathGrip = it;
-  nsresult rv = const_cast<HTMLScriptElement*>(this)->CopyInnerTo(it);
+  nsresult rv = const_cast<HTMLScriptElement*>(this)->CopyInnerTo(it, aPreallocateChildren);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // The clone should be marked evaluated if we are.
   it->mAlreadyStarted = mAlreadyStarted;
   it->mLineNumber = mLineNumber;
   it->mMalformed = mMalformed;
 
   kungFuDeathGrip.swap(*aResult);
--- a/dom/html/HTMLScriptElement.h
+++ b/dom/html/HTMLScriptElement.h
@@ -48,17 +48,18 @@ public:
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsIAtom* aAttribute,
                               const nsAString& aValue,
                               nsAttrValue& aResult) override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // Element
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
                                 const nsAttrValue* aValue, bool aNotify) override;
 
   // WebIDL
   void SetText(const nsAString& aValue, ErrorResult& rv);
   void SetCharset(const nsAString& aCharset, ErrorResult& rv);
--- a/dom/html/HTMLSelectElement.h
+++ b/dom/html/HTMLSelectElement.h
@@ -397,17 +397,18 @@ public:
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult) override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
                                               int32_t aModType) const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
+                         bool aPreallocateChildren) const override;
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLSelectElement,
                                            nsGenericHTMLFormElementWithState)
 
   HTMLOptionsCollection* GetOptions()
   {
     return mOptions;
   }
--- a/dom/html/HTMLShadowElement.h
+++ b/dom/html/HTMLShadowElement.h
@@ -34,17 +34,18 @@ public:
       return static_cast<HTMLShadowElement*>(aContent);
     }
 
     return nullptr;
   }
 
   virtual bool IsHTMLShadowElement() const override { return true; }
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
 
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
 
--- a/dom/html/HTMLSharedElement.h
+++ b/dom/html/HTMLSharedElement.h
@@ -76,17 +76,18 @@ public:
                               bool aCompileEventHandlers) override;
 
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
 
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL API
   // HTMLParamElement
   void GetName(DOMString& aValue)
   {
     MOZ_ASSERT(mNodeInfo->Equals(nsGkAtoms::param));
     GetHTMLAttr(nsGkAtoms::name, aValue);
   }
--- a/dom/html/HTMLSharedListElement.h
+++ b/dom/html/HTMLSharedListElement.h
@@ -36,17 +36,18 @@ public:
   // fully declared by NS_DECL_NSIDOMHTMLOLISTELEMENT
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult) override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   bool Reversed() const
   {
     return GetBoolAttr(nsGkAtoms::reversed);
   }
   void SetReversed(bool aReversed, mozilla::ErrorResult& rv)
   {
     SetHTMLBoolAttr(nsGkAtoms::reversed, aReversed, rv);
--- a/dom/html/HTMLSharedObjectElement.cpp
+++ b/dom/html/HTMLSharedObjectElement.cpp
@@ -341,19 +341,19 @@ HTMLSharedObjectElement::GetCapabilities
 void
 HTMLSharedObjectElement::DestroyContent()
 {
   nsObjectLoadingContent::DestroyContent();
   nsGenericHTMLElement::DestroyContent();
 }
 
 nsresult
-HTMLSharedObjectElement::CopyInnerTo(Element* aDest)
+HTMLSharedObjectElement::CopyInnerTo(Element* aDest, bool aPreallocateChildren)
 {
-  nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest);
+  nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest, aPreallocateChildren);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aDest->OwnerDoc()->IsStaticDocument()) {
     CreateStaticClone(static_cast<HTMLSharedObjectElement*>(aDest));
   }
 
   return rv;
 }
--- a/dom/html/HTMLSharedObjectElement.h
+++ b/dom/html/HTMLSharedObjectElement.h
@@ -74,19 +74,20 @@ public:
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom *aAttribute) const override;
   virtual EventStates IntrinsicState() const override;
   virtual void DestroyContent() override;
 
   // nsObjectLoadingContent
   virtual uint32_t GetCapabilities() const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
-  nsresult CopyInnerTo(Element* aDest);
+  nsresult CopyInnerTo(Element* aDest, bool aPreallocateChildren);
 
   void StartObjectLoad() { StartObjectLoad(true, false); }
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(HTMLSharedObjectElement,
                                                      nsGenericHTMLElement)
 
   // WebIDL API for <applet>
   void GetAlign(DOMString& aValue)
--- a/dom/html/HTMLSourceElement.h
+++ b/dom/html/HTMLSourceElement.h
@@ -30,17 +30,18 @@ public:
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLSourceElement,
                                            nsGenericHTMLElement)
 
   NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLSourceElement, source)
 
   // nsIDOMHTMLSourceElement
   NS_DECL_NSIDOMHTMLSOURCEELEMENT
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
+                         bool aPreallocateChildren) const override;
 
   // Override BindToTree() so that we can trigger a load when we add a
   // child source element.
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
 
   // If this element's media attr matches for its owner document.  Returns true
--- a/dom/html/HTMLSpanElement.h
+++ b/dom/html/HTMLSpanElement.h
@@ -21,17 +21,18 @@ namespace dom {
 class HTMLSpanElement final : public nsGenericHTMLElement
 {
 public:
   explicit HTMLSpanElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
 protected:
   virtual ~HTMLSpanElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 };
 
 } // namespace dom
--- a/dom/html/HTMLStyleElement.h
+++ b/dom/html/HTMLStyleElement.h
@@ -45,17 +45,18 @@ public:
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                                 const nsAttrValue* aValue,
                                 bool aNotify) override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // nsIMutationObserver
   NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
 
   bool Disabled();
--- a/dom/html/HTMLSummaryElement.h
+++ b/dom/html/HTMLSummaryElement.h
@@ -24,17 +24,18 @@ public:
 
   explicit HTMLSummaryElement(already_AddRefed<NodeInfo>& aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
 
   NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLSummaryElement, summary)
 
-  nsresult Clone(NodeInfo* aNodeInfo, nsINode** aResult) const override;
+  nsresult Clone(NodeInfo* aNodeInfo, nsINode** aResult,
+                 bool aPreallocateChildren) const override;
 
   nsresult PostHandleEvent(EventChainPostVisitor& aVisitor) override;
 
   bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
                        int32_t* aTabIndex) override;
 
   int32_t TabIndexDefault() override;
 
--- a/dom/html/HTMLTableCaptionElement.h
+++ b/dom/html/HTMLTableCaptionElement.h
@@ -32,17 +32,18 @@ public:
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult) override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
 protected:
   virtual ~HTMLTableCaptionElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
--- a/dom/html/HTMLTableCellElement.h
+++ b/dom/html/HTMLTableCellElement.h
@@ -146,17 +146,18 @@ public:
                               const nsAString& aValue,
                               nsAttrValue& aResult) override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
   // Get mapped attributes of ancestor table, if any
   nsMappedAttributes* GetMappedAttributesInheritedFromTable() const;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
 protected:
   virtual ~HTMLTableCellElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   HTMLTableElement* GetTable() const;
 
--- a/dom/html/HTMLTableColElement.h
+++ b/dom/html/HTMLTableColElement.h
@@ -74,17 +74,18 @@ public:
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult) override;
   nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
 protected:
   virtual ~HTMLTableColElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
--- a/dom/html/HTMLTableElement.h
+++ b/dom/html/HTMLTableElement.h
@@ -184,17 +184,18 @@ public:
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult) override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
   /**
    * Called when an attribute is about to be changed
--- a/dom/html/HTMLTableRowElement.h
+++ b/dom/html/HTMLTableRowElement.h
@@ -80,17 +80,18 @@ public:
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult) override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(HTMLTableRowElement,
                                                      nsGenericHTMLElement)
 
 protected:
   virtual ~HTMLTableRowElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
--- a/dom/html/HTMLTableSectionElement.h
+++ b/dom/html/HTMLTableSectionElement.h
@@ -65,17 +65,18 @@ public:
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsIAtom* aAttribute,
                               const nsAString& aValue,
                               nsAttrValue& aResult) override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(HTMLTableSectionElement,
                                                      nsGenericHTMLElement)
 protected:
   virtual ~HTMLTableSectionElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
--- a/dom/html/HTMLTemplateElement.h
+++ b/dom/html/HTMLTemplateElement.h
@@ -21,17 +21,18 @@ public:
   explicit HTMLTemplateElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLTemplateElement,
                                            nsGenericHTMLElement)
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   DocumentFragment* Content()
   {
     return mContent;
   }
 
 protected:
   virtual ~HTMLTemplateElement();
--- a/dom/html/HTMLTextAreaElement.cpp
+++ b/dom/html/HTMLTextAreaElement.cpp
@@ -97,24 +97,25 @@ NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION
                                nsIMutationObserver,
                                nsIConstraintValidation)
 NS_INTERFACE_TABLE_TAIL_INHERITING(nsGenericHTMLFormElementWithState)
 
 
 // nsIDOMHTMLTextAreaElement
 
 nsresult
-HTMLTextAreaElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const
+HTMLTextAreaElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                           bool aPreallocateChildren) const
 {
   *aResult = nullptr;
   already_AddRefed<mozilla::dom::NodeInfo> ni =
     RefPtr<mozilla::dom::NodeInfo>(aNodeInfo).forget();
   RefPtr<HTMLTextAreaElement> it = new HTMLTextAreaElement(ni);
 
-  nsresult rv = const_cast<HTMLTextAreaElement*>(this)->CopyInnerTo(it);
+  nsresult rv = const_cast<HTMLTextAreaElement*>(this)->CopyInnerTo(it, aPreallocateChildren);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (mValueChanged) {
     // Set our value on the clone.
     nsAutoString value;
     GetValueInternal(value, true);
 
     // SetValueInternal handles setting mValueChanged for us
@@ -1115,19 +1116,20 @@ HTMLTextAreaElement::AfterSetAttr(int32_
     }
   }
 
   return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName, aValue,
                                                          aNotify);
   }
 
 nsresult
-HTMLTextAreaElement::CopyInnerTo(Element* aDest)
+HTMLTextAreaElement::CopyInnerTo(Element* aDest, bool aPreallocateChildren)
 {
-  nsresult rv = nsGenericHTMLFormElementWithState::CopyInnerTo(aDest);
+  nsresult rv = nsGenericHTMLFormElementWithState::CopyInnerTo(aDest,
+                                                               aPreallocateChildren);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aDest->OwnerDoc()->IsStaticDocument()) {
     nsAutoString value;
     GetValueInternal(value, true);
     return static_cast<HTMLTextAreaElement*>(aDest)->SetValue(value);
   }
   return NS_OK;
--- a/dom/html/HTMLTextAreaElement.h
+++ b/dom/html/HTMLTextAreaElement.h
@@ -140,19 +140,20 @@ public:
   virtual nsresult PostHandleEvent(
                      EventChainPostVisitor& aVisitor) override;
 
   virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex) override;
 
   virtual void DoneAddingChildren(bool aHaveNotified) override;
   virtual bool IsDoneAddingChildren() override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
-  nsresult CopyInnerTo(Element* aDest);
+  nsresult CopyInnerTo(Element* aDest, bool aPreallocateChildren);
 
   /**
    * Called when an attribute is about to be changed
    */
   virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                                  const nsAttrValueOrString* aValue,
                                  bool aNotify) override;
 
--- a/dom/html/HTMLTimeElement.h
+++ b/dom/html/HTMLTimeElement.h
@@ -27,17 +27,18 @@ public:
     GetHTMLAttr(nsGkAtoms::datetime, aDateTime);
   }
 
   void SetDateTime(const nsAString& aDateTime, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::datetime, aDateTime, aError);
   }
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
+                         bool aPreallocateChildren) const override;
 
 protected:
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 };
 
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/html/HTMLTitleElement.h
+++ b/dom/html/HTMLTitleElement.h
@@ -33,17 +33,18 @@ public:
   void SetText(const nsAString& aText, ErrorResult& aError);
 
   // nsIMutationObserver
   NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   virtual nsresult BindToTree(nsIDocument *aDocument, nsIContent *aParent,
                               nsIContent *aBindingParent,
                               bool aCompileEventHandlers) override;
 
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
 
--- a/dom/html/HTMLTrackElement.h
+++ b/dom/html/HTMLTrackElement.h
@@ -85,17 +85,18 @@ public:
     SetHTMLBoolAttr(nsGkAtoms::_default, aDefault, aError);
   }
 
   uint16_t ReadyState() const;
   void SetReadyState(uint16_t aReadyState);
 
   TextTrack* GetTrack();
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
+                         bool aPreallocateChildren) const override;
 
   // Override ParseAttribute() to convert kind strings to enum values.
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsIAtom* aAttribute,
                               const nsAString& aValue,
                               nsAttrValue& aResult) override;
 
   // Override BindToTree() so that we can trigger a load when we become
--- a/dom/html/HTMLUnknownElement.h
+++ b/dom/html/HTMLUnknownElement.h
@@ -26,17 +26,18 @@ public:
   explicit HTMLUnknownElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
     if (NodeInfo()->Equals(nsGkAtoms::bdi)) {
       SetHasDirAuto();
     }
   }
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
 protected:
   virtual ~HTMLUnknownElement() {}
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(HTMLUnknownElement, NS_HTMLUNKNOWNELEMENT_IID)
 
--- a/dom/html/HTMLVideoElement.h
+++ b/dom/html/HTMLVideoElement.h
@@ -36,17 +36,18 @@ public:
                               const nsAString& aValue,
                               nsAttrValue& aResult) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
 
   static void Init();
 
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
 
-  virtual nsresult Clone(NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // Set size with the current video frame's height and width.
   // If there is no video frame, returns NS_ERROR_FAILURE.
   nsresult GetVideoSize(nsIntSize* size);
 
   virtual nsresult SetAcceptHeader(nsIHttpChannel* aChannel) override;
 
   // Element
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -170,19 +170,24 @@ NS_IMPL_RELEASE_INHERITED(nsGenericHTMLE
 
 NS_INTERFACE_MAP_BEGIN(nsGenericHTMLElement)
   NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLElement)
   NS_INTERFACE_MAP_ENTRY(nsIDOMElement)
   NS_INTERFACE_MAP_ENTRY(nsIDOMNode)
 NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElementBase)
 
 nsresult
-nsGenericHTMLElement::CopyInnerTo(Element* aDst)
+nsGenericHTMLElement::CopyInnerTo(Element* aDst, bool aPreallocateChildren)
 {
   nsresult rv;
+
+  rv = static_cast<nsGenericHTMLElement*>(aDst)->mAttrsAndChildren.
+       EnsureCapacityToClone(mAttrsAndChildren, aPreallocateChildren);
+  NS_ENSURE_SUCCESS(rv, rv);
+
   int32_t i, count = GetAttrCount();
   for (i = 0; i < count; ++i) {
     const nsAttrName *name = mAttrsAndChildren.AttrNameAt(i);
     const nsAttrValue *value = mAttrsAndChildren.AttrAt(i);
 
     nsAutoString valStr;
     value->ToString(valStr);
 
--- a/dom/html/nsGenericHTMLElement.h
+++ b/dom/html/nsGenericHTMLElement.h
@@ -63,17 +63,17 @@ public:
     SetFlags(NODE_HAS_DIRECTION_LTR);
   }
 
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_IMPL_FROMCONTENT(nsGenericHTMLElement, kNameSpaceID_XHTML)
 
   // From Element
-  nsresult CopyInnerTo(mozilla::dom::Element* aDest);
+  nsresult CopyInnerTo(mozilla::dom::Element* aDest, bool aPreallocateChildren);
 
   void GetTitle(mozilla::dom::DOMString& aTitle)
   {
     GetHTMLAttr(nsGkAtoms::title, aTitle);
   }
   NS_IMETHOD SetTitle(const nsAString& aTitle) override
   {
     SetHTMLAttr(nsGkAtoms::title, aTitle);
--- a/dom/html/nsGenericHTMLFrameElement.cpp
+++ b/dom/html/nsGenericHTMLFrameElement.cpp
@@ -428,19 +428,20 @@ nsGenericHTMLFrameElement::DestroyConten
     mFrameLoader->Destroy();
     mFrameLoader = nullptr;
   }
 
   nsGenericHTMLElement::DestroyContent();
 }
 
 nsresult
-nsGenericHTMLFrameElement::CopyInnerTo(Element* aDest)
+nsGenericHTMLFrameElement::CopyInnerTo(Element* aDest,
+                                       bool aPreallocateChildren)
 {
-  nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest);
+  nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest, aPreallocateChildren);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsIDocument* doc = aDest->OwnerDoc();
   if (doc->IsStaticDocument() && mFrameLoader) {
     nsGenericHTMLFrameElement* dest =
       static_cast<nsGenericHTMLFrameElement*>(aDest);
     nsFrameLoader* fl = nsFrameLoader::Create(dest, nullptr, false);
     NS_ENSURE_STATE(fl);
--- a/dom/html/nsGenericHTMLFrameElement.h
+++ b/dom/html/nsGenericHTMLFrameElement.h
@@ -63,17 +63,17 @@ public:
                            bool aNotify) override;
   virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
                              bool aNotify) override;
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                                 const nsAttrValue* aValue,
                                 bool aNotify) override;
   virtual void DestroyContent() override;
 
-  nsresult CopyInnerTo(mozilla::dom::Element* aDest);
+  nsresult CopyInnerTo(mozilla::dom::Element* aDest, bool aPreallocateChildren);
 
   virtual int32_t TabIndexDefault() override;
 
   virtual nsIMozBrowserFrame* GetAsMozBrowserFrame() override { return this; }
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsGenericHTMLFrameElement,
                                            nsGenericHTMLElement)
 
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -3649,23 +3649,24 @@ nsHTMLDocument::QueryCommandValue(const 
   // regardless.
   nsXPIDLCString cStringResult;
   cmdParams->GetCStringValue("state_attribute",
                              getter_Copies(cStringResult));
   CopyUTF8toUTF16(cStringResult, aValue);
 }
 
 nsresult
-nsHTMLDocument::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const
+nsHTMLDocument::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                      bool aPreallocateChildren) const
 {
   NS_ASSERTION(aNodeInfo->NodeInfoManager() == mNodeInfoManager,
                "Can't import this document into another document!");
 
   RefPtr<nsHTMLDocument> clone = new nsHTMLDocument();
-  nsresult rv = CloneDocHelper(clone.get());
+  nsresult rv = CloneDocHelper(clone.get(), aPreallocateChildren);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // State from nsHTMLDocument
   clone->mLoadFlags = mLoadFlags;
 
   return CallQueryInterface(clone.get(), aResult);
 }
 
--- a/dom/html/nsHTMLDocument.h
+++ b/dom/html/nsHTMLDocument.h
@@ -143,17 +143,18 @@ public:
   friend class nsAutoEditingState;
 
   void EndUpdate(nsUpdateType aUpdateType) override;
 
   virtual void SetMayStartLayout(bool aMayStartLayout) override;
 
   virtual nsresult SetEditingState(EditingState aState) override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   virtual void RemovedFromDocShell() override;
 
   virtual mozilla::dom::Element *GetElementById(const nsAString& aElementId) override
   {
     return nsDocument::GetElementById(aElementId);
   }
 
--- a/dom/mathml/nsMathMLElement.h
+++ b/dom/mathml/nsMathMLElement.h
@@ -73,17 +73,18 @@ public:
 
   static void MapMathMLAttributesInto(const nsMappedAttributes* aAttributes, 
                                       mozilla::GenericSpecifiedValues* aGenericData);
   
   virtual nsresult GetEventTargetParent(
                      mozilla::EventChainPreVisitor& aVisitor) override;
   virtual nsresult PostHandleEvent(
                      mozilla::EventChainPostVisitor& aVisitor) override;
-  nsresult Clone(mozilla::dom::NodeInfo*, nsINode**) const override;
+  nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
+                 bool aPreallocateChildren) const override;
   virtual mozilla::EventStates IntrinsicState() const override;
   virtual bool IsNodeOfType(uint32_t aFlags) const override;
 
   // Set during reflow as necessary. Does a style change notification,
   // aNotify must be true.
   void SetIncrementScriptLevel(bool aIncrementScriptLevel, bool aNotify);
   bool GetIncrementScriptLevel() const {
     return mIncrementScriptLevel;
--- a/dom/svg/SVGAElement.h
+++ b/dom/svg/SVGAElement.h
@@ -36,17 +36,18 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SVGAElement, SVGAElementBase)
 
   // nsINode interface methods
   virtual nsresult GetEventTargetParent(
                      EventChainPreVisitor& aVisitor) override;
   virtual nsresult PostHandleEvent(
                      EventChainPostVisitor& aVisitor) override;
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // nsIContent
   virtual nsresult BindToTree(nsIDocument *aDocument, nsIContent *aParent,
                               nsIContent *aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
--- a/dom/svg/SVGAnimateElement.h
+++ b/dom/svg/SVGAnimateElement.h
@@ -26,17 +26,18 @@ protected:
   friend nsresult
     (::NS_NewSVGAnimateElement(nsIContent **aResult,
                                already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 public:
   // nsIDOMNode
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // SVGAnimationElement
   virtual nsSMILAnimationFunction& AnimationFunction() override;
 };
 
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/svg/SVGAnimateMotionElement.h
+++ b/dom/svg/SVGAnimateMotionElement.h
@@ -26,17 +26,18 @@ protected:
   friend nsresult
     (::NS_NewSVGAnimateMotionElement(nsIContent **aResult,
                                      already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 public:
   // nsIDOMNode specializations
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // SVGAnimationElement
   virtual nsSMILAnimationFunction& AnimationFunction() override;
   virtual bool GetTargetAttributeName(int32_t *aNamespaceID,
                                       nsIAtom **aLocalName) const override;
 
   // nsSVGElement
   virtual nsIAtom* GetPathDataAttrName() const override {
--- a/dom/svg/SVGAnimateTransformElement.h
+++ b/dom/svg/SVGAnimateTransformElement.h
@@ -26,17 +26,18 @@ protected:
   friend nsresult
     (::NS_NewSVGAnimateTransformElement(nsIContent **aResult,
                                         already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 public:
   // nsIDOMNode specializations
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // Element specializations
   bool ParseAttribute(int32_t aNamespaceID,
                         nsIAtom* aAttribute,
                         const nsAString& aValue,
                         nsAttrValue& aResult) override;
 
   // SVGAnimationElement
--- a/dom/svg/SVGAnimationElement.h
+++ b/dom/svg/SVGAnimationElement.h
@@ -34,17 +34,18 @@ protected:
 
 public:
   // interfaces:
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SVGAnimationElement,
                                            SVGAnimationElementBase)
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override = 0;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override = 0;
 
   // nsIContent specializations
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
 
   virtual nsresult UnsetAttr(int32_t aNamespaceID, nsIAtom* aAttribute,
--- a/dom/svg/SVGCircleElement.h
+++ b/dom/svg/SVGCircleElement.h
@@ -31,17 +31,18 @@ public:
   virtual bool HasValidDimensions() const override;
 
   // SVGGeometryElement methods:
   virtual bool GetGeometryBounds(Rect* aBounds, const StrokeOptions& aStrokeOptions,
                                  const Matrix& aToBoundsSpace,
                                  const Matrix* aToNonScalingStrokeSpace = nullptr) override;
   virtual already_AddRefed<Path> BuildPath(PathBuilder* aBuilder) override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedLength> Cx();
   already_AddRefed<SVGAnimatedLength> Cy();
   already_AddRefed<SVGAnimatedLength> R();
 
 protected:
 
--- a/dom/svg/SVGClipPathElement.h
+++ b/dom/svg/SVGClipPathElement.h
@@ -26,17 +26,18 @@ class SVGClipPathElement final : public 
 
 protected:
   friend nsresult (::NS_NewSVGClipPathElement(nsIContent **aResult,
                                               already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
   explicit SVGClipPathElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
   virtual JSObject* WrapNode(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
 
 public:
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedEnumeration> ClipPathUnits();
 
 protected:
 
   enum { CLIPPATHUNITS };
   nsSVGEnum mEnumAttributes[1];
--- a/dom/svg/SVGComponentTransferFunctionElement.h
+++ b/dom/svg/SVGComponentTransferFunctionElement.h
@@ -96,17 +96,18 @@ class SVGFEFuncRElement : public SVGComp
     nsIContent** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
 protected:
   explicit SVGFEFuncRElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
     : SVGComponentTransferFunctionElement(aNodeInfo) {}
 
 public:
   virtual int32_t GetChannel() override { return 0; }
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 nsresult NS_NewSVGFEFuncGElement(
@@ -121,17 +122,18 @@ class SVGFEFuncGElement : public SVGComp
     nsIContent** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
 protected:
   explicit SVGFEFuncGElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
     : SVGComponentTransferFunctionElement(aNodeInfo) {}
 
 public:
   virtual int32_t GetChannel() override { return 1; }
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 nsresult NS_NewSVGFEFuncBElement(
@@ -146,17 +148,18 @@ class SVGFEFuncBElement : public SVGComp
     nsIContent** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
 protected:
   explicit SVGFEFuncBElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
     : SVGComponentTransferFunctionElement(aNodeInfo) {}
 
 public:
   virtual int32_t GetChannel() override { return 2; }
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 nsresult NS_NewSVGFEFuncAElement(
@@ -171,17 +174,18 @@ class SVGFEFuncAElement : public SVGComp
     nsIContent** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
 protected:
   explicit SVGFEFuncAElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
     : SVGComponentTransferFunctionElement(aNodeInfo) {}
 
 public:
   virtual int32_t GetChannel() override { return 3; }
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_SVGComponentTransferFunctionElement_h
--- a/dom/svg/SVGDefsElement.h
+++ b/dom/svg/SVGDefsElement.h
@@ -22,15 +22,16 @@ protected:
                                           already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
   explicit SVGDefsElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 public:
   // nsIContent
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_SVGDefsElement_h
--- a/dom/svg/SVGDescElement.h
+++ b/dom/svg/SVGDescElement.h
@@ -23,16 +23,17 @@ class SVGDescElement final : public SVGD
 protected:
   friend nsresult (::NS_NewSVGDescElement(nsIContent **aResult,
                                           already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
   explicit SVGDescElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
 
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 public:
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_SVGDescElement_h
 
--- a/dom/svg/SVGDocument.cpp
+++ b/dom/svg/SVGDocument.cpp
@@ -46,23 +46,24 @@ SVGDocument::InsertChildAt(nsIContent* a
     // loaded by then.
     EnsureNonSVGUserAgentStyleSheetsLoaded();
   }
 
   return XMLDocument::InsertChildAt(aKid, aIndex, aNotify);
 }
 
 nsresult
-SVGDocument::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const
+SVGDocument::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                   bool aPreallocateChildren) const
 {
   NS_ASSERTION(aNodeInfo->NodeInfoManager() == mNodeInfoManager,
                "Can't import this document into another document!");
 
   RefPtr<SVGDocument> clone = new SVGDocument();
-  nsresult rv = CloneDocHelper(clone.get());
+  nsresult rv = CloneDocHelper(clone.get(), aPreallocateChildren);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return CallQueryInterface(clone.get(), aResult);
 }
 
 void
 SVGDocument::EnsureNonSVGUserAgentStyleSheetsLoaded()
 {
--- a/dom/svg/SVGDocument.h
+++ b/dom/svg/SVGDocument.h
@@ -26,17 +26,18 @@ public:
     : XMLDocument("image/svg+xml")
     , mHasLoadedNonSVGUserAgentStyleSheets(false)
   {
     mType = eSVG;
   }
 
   virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex,
                                  bool aNotify) override;
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   virtual SVGDocument* AsSVGDocument() override {
     return this;
   }
 
 private:
   void EnsureNonSVGUserAgentStyleSheetsLoaded();
 
--- a/dom/svg/SVGEllipseElement.h
+++ b/dom/svg/SVGEllipseElement.h
@@ -31,17 +31,18 @@ public:
   virtual bool HasValidDimensions() const override;
 
   // SVGGeometryElement methods:
   virtual bool GetGeometryBounds(Rect* aBounds, const StrokeOptions& aStrokeOptions,
                                  const Matrix& aToBoundsSpace,
                                  const Matrix* aToNonScalingStrokeSpace = nullptr) override;
   virtual already_AddRefed<Path> BuildPath(PathBuilder* aBuilder) override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedLength> Cx();
   already_AddRefed<SVGAnimatedLength> Cy();
   already_AddRefed<SVGAnimatedLength> Rx();
   already_AddRefed<SVGAnimatedLength> Ry();
 
 protected:
--- a/dom/svg/SVGFEBlendElement.h
+++ b/dom/svg/SVGFEBlendElement.h
@@ -34,17 +34,18 @@ public:
                             const IntRect& aFilterSubregion,
                             const nsTArray<bool>& aInputsAreTainted,
                             nsTArray<RefPtr<SourceSurface>>& aInputImages) override;
   virtual bool AttributeAffectsRendering(
           int32_t aNameSpaceID, nsIAtom* aAttribute) const override;
   virtual nsSVGString& GetResultImageName() override { return mStringAttributes[RESULT]; }
   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedString> In1();
   already_AddRefed<SVGAnimatedString> In2();
   already_AddRefed<SVGAnimatedEnumeration> Mode();
 
 protected:
 
--- a/dom/svg/SVGFEColorMatrixElement.h
+++ b/dom/svg/SVGFEColorMatrixElement.h
@@ -36,17 +36,18 @@ public:
                             const IntRect& aFilterSubregion,
                             const nsTArray<bool>& aInputsAreTainted,
                             nsTArray<RefPtr<SourceSurface>>& aInputImages) override;
   virtual bool AttributeAffectsRendering(
           int32_t aNameSpaceID, nsIAtom* aAttribute) const override;
   virtual nsSVGString& GetResultImageName() override { return mStringAttributes[RESULT]; }
   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedString> In1();
   already_AddRefed<SVGAnimatedEnumeration> Type();
   already_AddRefed<DOMSVGAnimatedNumberList> Values();
 
  protected:
   virtual EnumAttributesInfo GetEnumInfo() override;
--- a/dom/svg/SVGFEComponentTransferElement.h
+++ b/dom/svg/SVGFEComponentTransferElement.h
@@ -35,17 +35,18 @@ public:
                             const nsTArray<bool>& aInputsAreTainted,
                             nsTArray<RefPtr<SourceSurface>>& aInputImages) override;
   virtual bool AttributeAffectsRendering(
           int32_t aNameSpaceID, nsIAtom* aAttribute) const override;
   virtual nsSVGString& GetResultImageName() override { return mStringAttributes[RESULT]; }
   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) override;
 
   // nsIContent
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedString> In1();
 
 protected:
   virtual StringAttributesInfo GetStringInfo() override;
 
   enum { RESULT, IN1 };
--- a/dom/svg/SVGFECompositeElement.h
+++ b/dom/svg/SVGFECompositeElement.h
@@ -37,17 +37,18 @@ public:
                             const nsTArray<bool>& aInputsAreTainted,
                             nsTArray<RefPtr<SourceSurface>>& aInputImages) override;
   virtual bool AttributeAffectsRendering(
           int32_t aNameSpaceID, nsIAtom* aAttribute) const override;
   virtual nsSVGString& GetResultImageName() override { return mStringAttributes[RESULT]; }
   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) override;
 
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedString> In1();
   already_AddRefed<SVGAnimatedString> In2();
   already_AddRefed<SVGAnimatedEnumeration> Operator();
   already_AddRefed<SVGAnimatedNumber> K1();
   already_AddRefed<SVGAnimatedNumber> K2();
   already_AddRefed<SVGAnimatedNumber> K3();
--- a/dom/svg/SVGFEConvolveMatrixElement.h
+++ b/dom/svg/SVGFEConvolveMatrixElement.h
@@ -44,17 +44,18 @@ public:
                             const IntRect& aFilterSubregion,
                             const nsTArray<bool>& aInputsAreTainted,
                             nsTArray<RefPtr<SourceSurface>>& aInputImages) override;
   virtual bool AttributeAffectsRendering(
           int32_t aNameSpaceID, nsIAtom* aAttribute) const override;
   virtual nsSVGString& GetResultImageName() override { return mStringAttributes[RESULT]; }
   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedString> In1();
   already_AddRefed<SVGAnimatedInteger> OrderX();
   already_AddRefed<SVGAnimatedInteger> OrderY();
   already_AddRefed<DOMSVGAnimatedNumberList> KernelMatrix();
   already_AddRefed<SVGAnimatedInteger> TargetX();
   already_AddRefed<SVGAnimatedInteger> TargetY();
--- a/dom/svg/SVGFEDiffuseLightingElement.h
+++ b/dom/svg/SVGFEDiffuseLightingElement.h
@@ -32,17 +32,18 @@ public:
   virtual FilterPrimitiveDescription
     GetPrimitiveDescription(nsSVGFilterInstance* aInstance,
                             const IntRect& aFilterSubregion,
                             const nsTArray<bool>& aInputsAreTainted,
                             nsTArray<RefPtr<SourceSurface>>& aInputImages) override;
   virtual bool AttributeAffectsRendering(
           int32_t aNameSpaceID, nsIAtom* aAttribute) const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedString> In1();
   already_AddRefed<SVGAnimatedNumber> SurfaceScale();
   already_AddRefed<SVGAnimatedNumber> DiffuseConstant();
   already_AddRefed<SVGAnimatedNumber> KernelUnitLengthX();
   already_AddRefed<SVGAnimatedNumber> KernelUnitLengthY();
 };
--- a/dom/svg/SVGFEDisplacementMapElement.h
+++ b/dom/svg/SVGFEDisplacementMapElement.h
@@ -35,17 +35,18 @@ public:
                             const IntRect& aFilterSubregion,
                             const nsTArray<bool>& aInputsAreTainted,
                             nsTArray<RefPtr<SourceSurface>>& aInputImages) override;
   virtual bool AttributeAffectsRendering(
           int32_t aNameSpaceID, nsIAtom* aAttribute) const override;
   virtual nsSVGString& GetResultImageName() override { return mStringAttributes[RESULT]; }
   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedString> In1();
   already_AddRefed<SVGAnimatedString> In2();
   already_AddRefed<SVGAnimatedNumber> Scale();
   already_AddRefed<SVGAnimatedEnumeration> XChannelSelector();
   already_AddRefed<SVGAnimatedEnumeration> YChannelSelector();
 
--- a/dom/svg/SVGFEDistantLightElement.h
+++ b/dom/svg/SVGFEDistantLightElement.h
@@ -29,17 +29,18 @@ protected:
   }
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 public:
   virtual AttributeMap ComputeLightAttributes(nsSVGFilterInstance* aInstance) override;
   virtual bool AttributeAffectsRendering(
           int32_t aNameSpaceID, nsIAtom* aAttribute) const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedNumber> Azimuth();
   already_AddRefed<SVGAnimatedNumber> Elevation();
 
 protected:
   virtual NumberAttributesInfo GetNumberInfo() override;
 
--- a/dom/svg/SVGFEDropShadowElement.h
+++ b/dom/svg/SVGFEDropShadowElement.h
@@ -40,17 +40,18 @@ public:
   virtual bool AttributeAffectsRendering(
           int32_t aNameSpaceID, nsIAtom* aAttribute) const override;
   virtual nsSVGString& GetResultImageName() override { return mStringAttributes[RESULT]; }
   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo >& aSources) override;
 
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedString> In1();
   already_AddRefed<SVGAnimatedNumber> Dx();
   already_AddRefed<SVGAnimatedNumber> Dy();
   already_AddRefed<SVGAnimatedNumber> StdDeviationX();
   already_AddRefed<SVGAnimatedNumber> StdDeviationY();
   void SetStdDeviation(float stdDeviationX, float stdDeviationY);
--- a/dom/svg/SVGFEFloodElement.h
+++ b/dom/svg/SVGFEFloodElement.h
@@ -36,17 +36,18 @@ public:
                             const IntRect& aFilterSubregion,
                             const nsTArray<bool>& aInputsAreTainted,
                             nsTArray<RefPtr<SourceSurface>>& aInputImages) override;
   virtual nsSVGString& GetResultImageName() override { return mStringAttributes[RESULT]; }
 
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
 protected:
   virtual bool ProducesSRGB() override { return true; }
 
   virtual StringAttributesInfo GetStringInfo() override;
 
   enum { RESULT };
   nsSVGString mStringAttributes[1];
--- a/dom/svg/SVGFEGaussianBlurElement.h
+++ b/dom/svg/SVGFEGaussianBlurElement.h
@@ -36,17 +36,18 @@ public:
                             const IntRect& aFilterSubregion,
                             const nsTArray<bool>& aInputsAreTainted,
                             nsTArray<RefPtr<SourceSurface>>& aInputImages) override;
   virtual bool AttributeAffectsRendering(
           int32_t aNameSpaceID, nsIAtom* aAttribute) const override;
   virtual nsSVGString& GetResultImageName() override { return mStringAttributes[RESULT]; }
   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo >& aSources) override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedString> In1();
   already_AddRefed<SVGAnimatedNumber> StdDeviationX();
   already_AddRefed<SVGAnimatedNumber> StdDeviationY();
   void SetStdDeviation(float stdDeviationX, float stdDeviationY);
 
 protected:
--- a/dom/svg/SVGFEImageElement.h
+++ b/dom/svg/SVGFEImageElement.h
@@ -50,17 +50,18 @@ public:
           int32_t aNameSpaceID, nsIAtom* aAttribute) const override;
   virtual nsSVGString& GetResultImageName() override { return mStringAttributes[RESULT]; }
   virtual bool OutputIsTainted(const nsTArray<bool>& aInputsAreTainted,
                                nsIPrincipal* aReferencePrincipal) override;
 
   // nsIContent
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
                                 const nsAttrValue* aValue, bool aNotify) override;
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
   virtual EventStates IntrinsicState() const override;
--- a/dom/svg/SVGFEMergeElement.h
+++ b/dom/svg/SVGFEMergeElement.h
@@ -33,17 +33,18 @@ public:
     GetPrimitiveDescription(nsSVGFilterInstance* aInstance,
                             const IntRect& aFilterSubregion,
                             const nsTArray<bool>& aInputsAreTainted,
                             nsTArray<RefPtr<SourceSurface>>& aInputImages) override;
   virtual nsSVGString& GetResultImageName() override { return mStringAttributes[RESULT]; }
   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) override;
 
   // nsIContent
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 protected:
   virtual StringAttributesInfo GetStringInfo() override;
 
   enum { RESULT };
   nsSVGString mStringAttributes[1];
   static StringInfo sStringInfo[1];
 };
 
--- a/dom/svg/SVGFEMergeNodeElement.h
+++ b/dom/svg/SVGFEMergeNodeElement.h
@@ -24,17 +24,18 @@ class SVGFEMergeNodeElement : public SVG
 protected:
   explicit SVGFEMergeNodeElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
     : SVGFEMergeNodeElementBase(aNodeInfo)
   {
   }
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 public:
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   virtual bool AttributeAffectsRendering(
           int32_t aNameSpaceID, nsIAtom* aAttribute) const override;
 
   const nsSVGString* GetIn1() { return &mStringAttributes[IN1]; }
 
   // WebIDL
   already_AddRefed<SVGAnimatedString> In1();
--- a/dom/svg/SVGFEMorphologyElement.h
+++ b/dom/svg/SVGFEMorphologyElement.h
@@ -37,17 +37,18 @@ public:
                             const IntRect& aFilterSubregion,
                             const nsTArray<bool>& aInputsAreTainted,
                             nsTArray<RefPtr<SourceSurface>>& aInputImages) override;
   virtual bool AttributeAffectsRendering(
           int32_t aNameSpaceID, nsIAtom* aAttribute) const override;
   virtual nsSVGString& GetResultImageName() override { return mStringAttributes[RESULT]; }
   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedString> In1();
   already_AddRefed<SVGAnimatedEnumeration> Operator();
   already_AddRefed<SVGAnimatedNumber> RadiusX();
   already_AddRefed<SVGAnimatedNumber> RadiusY();
   void SetRadius(float rx, float ry);
 
--- a/dom/svg/SVGFEOffsetElement.h
+++ b/dom/svg/SVGFEOffsetElement.h
@@ -36,17 +36,18 @@ public:
                             const IntRect& aFilterSubregion,
                             const nsTArray<bool>& aInputsAreTainted,
                             nsTArray<RefPtr<SourceSurface>>& aInputImages) override;
   virtual bool AttributeAffectsRendering(
           int32_t aNameSpaceID, nsIAtom* aAttribute) const override;
   virtual nsSVGString& GetResultImageName() override { return mStringAttributes[RESULT]; }
   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedString> In1();
   already_AddRefed<SVGAnimatedNumber> Dx();
   already_AddRefed<SVGAnimatedNumber> Dy();
 
 protected:
   virtual NumberAttributesInfo GetNumberInfo() override;
--- a/dom/svg/SVGFEPointLightElement.h
+++ b/dom/svg/SVGFEPointLightElement.h
@@ -29,17 +29,18 @@ protected:
   }
   virtual JSObject* WrapNode(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
 
 public:
   virtual AttributeMap ComputeLightAttributes(nsSVGFilterInstance* aInstance) override;
   virtual bool AttributeAffectsRendering(
           int32_t aNameSpaceID, nsIAtom* aAttribute) const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedNumber> X();
   already_AddRefed<SVGAnimatedNumber> Y();
   already_AddRefed<SVGAnimatedNumber> Z();
 
 protected:
   virtual NumberAttributesInfo GetNumberInfo() override;
--- a/dom/svg/SVGFESpecularLightingElement.h
+++ b/dom/svg/SVGFESpecularLightingElement.h
@@ -26,17 +26,18 @@ class SVGFESpecularLightingElement : pub
 protected:
   explicit SVGFESpecularLightingElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
     : SVGFESpecularLightingElementBase(aNodeInfo)
   {
   }
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 public:
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   virtual FilterPrimitiveDescription
     GetPrimitiveDescription(nsSVGFilterInstance* aInstance,
                             const IntRect& aFilterSubregion,
                             const nsTArray<bool>& aInputsAreTainted,
                             nsTArray<RefPtr<SourceSurface>>& aInputImages) override;
   virtual bool AttributeAffectsRendering(
           int32_t aNameSpaceID, nsIAtom* aAttribute) const override;
--- a/dom/svg/SVGFESpotLightElement.h
+++ b/dom/svg/SVGFESpotLightElement.h
@@ -30,17 +30,18 @@ protected:
   }
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 public:
   virtual AttributeMap ComputeLightAttributes(nsSVGFilterInstance* aInstance) override;
   virtual bool AttributeAffectsRendering(
           int32_t aNameSpaceID, nsIAtom* aAttribute) const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedNumber> X();
   already_AddRefed<SVGAnimatedNumber> Y();
   already_AddRefed<SVGAnimatedNumber> Z();
   already_AddRefed<SVGAnimatedNumber> PointsAtX();
   already_AddRefed<SVGAnimatedNumber> PointsAtY();
   already_AddRefed<SVGAnimatedNumber> PointsAtZ();
--- a/dom/svg/SVGFETileElement.h
+++ b/dom/svg/SVGFETileElement.h
@@ -36,17 +36,18 @@ public:
                             const IntRect& aFilterSubregion,
                             const nsTArray<bool>& aInputsAreTainted,
                             nsTArray<RefPtr<SourceSurface>>& aInputImages) override;
   virtual bool AttributeAffectsRendering(
           int32_t aNameSpaceID, nsIAtom* aAttribute) const override;
   virtual nsSVGString& GetResultImageName() override { return mStringAttributes[RESULT]; }
   virtual void GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources) override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedString> In1();
 
 protected:
   virtual StringAttributesInfo GetStringInfo() override;
 
   enum { RESULT, IN1 };
--- a/dom/svg/SVGFETurbulenceElement.h
+++ b/dom/svg/SVGFETurbulenceElement.h
@@ -39,17 +39,18 @@ public:
     GetPrimitiveDescription(nsSVGFilterInstance* aInstance,
                             const IntRect& aFilterSubregion,
                             const nsTArray<bool>& aInputsAreTainted,
                             nsTArray<RefPtr<SourceSurface>>& aInputImages) override;
   virtual bool AttributeAffectsRendering(
           int32_t aNameSpaceID, nsIAtom* aAttribute) const override;
   virtual nsSVGString& GetResultImageName() override { return mStringAttributes[RESULT]; }
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedNumber> BaseFrequencyX();
   already_AddRefed<SVGAnimatedNumber> BaseFrequencyY();
   already_AddRefed<SVGAnimatedInteger> NumOctaves();
   already_AddRefed<SVGAnimatedNumber> Seed();
   already_AddRefed<SVGAnimatedEnumeration> StitchTiles();
   already_AddRefed<SVGAnimatedEnumeration> Type();
--- a/dom/svg/SVGFilterElement.h
+++ b/dom/svg/SVGFilterElement.h
@@ -33,17 +33,18 @@ class SVGFilterElement : public SVGFilte
 protected:
   friend nsresult (::NS_NewSVGFilterElement(nsIContent **aResult,
                                             already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
   explicit SVGFilterElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
   virtual JSObject* WrapNode(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
 
 public:
   // nsIContent
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
 
   // Invalidate users of this filter
   void Invalidate();
 
   // nsSVGSVGElement methods:
   virtual bool HasValidDimensions() const override;
 
--- a/dom/svg/SVGForeignObjectElement.h
+++ b/dom/svg/SVGForeignObjectElement.h
@@ -36,17 +36,18 @@ public:
   virtual bool HasValidDimensions() const override;
 
   // nsIContent interface
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* name) const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedLength> X();
   already_AddRefed<SVGAnimatedLength> Y();
   already_AddRefed<SVGAnimatedLength> Width();
   already_AddRefed<SVGAnimatedLength> Height();
 
 protected:
--- a/dom/svg/SVGGElement.h
+++ b/dom/svg/SVGGElement.h
@@ -22,15 +22,16 @@ protected:
   virtual JSObject* WrapNode(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
   friend nsresult (::NS_NewSVGGElement(nsIContent **aResult,
                                        already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
 
 public:
   // nsIContent
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_SVGGElement_h
--- a/dom/svg/SVGGradientElement.h
+++ b/dom/svg/SVGGradientElement.h
@@ -43,17 +43,18 @@ class SVGGradientElement : public SVGGra
 {
   friend class ::nsSVGGradientFrame;
 
 protected:
   explicit SVGGradientElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override = 0;
 
 public:
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override = 0;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override = 0;
 
   // nsIContent
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
 
   virtual nsSVGAnimatedTransformList*
     GetAnimatedTransformList(uint32_t aFlags = 0) override;
   virtual nsIAtom* GetTransformListAttrName() const override {
     return nsGkAtoms::gradientTransform;
@@ -93,17 +94,18 @@ class SVGLinearGradientElement : public 
     (::NS_NewSVGLinearGradientElement(nsIContent** aResult,
                                       already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
 
 protected:
   explicit SVGLinearGradientElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 public:
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedLength> X1();
   already_AddRefed<SVGAnimatedLength> Y1();
   already_AddRefed<SVGAnimatedLength> X2();
   already_AddRefed<SVGAnimatedLength> Y2();
 
 protected:
@@ -126,17 +128,18 @@ class SVGRadialGradientElement : public 
     (::NS_NewSVGRadialGradientElement(nsIContent** aResult,
                                       already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
 
 protected:
   explicit SVGRadialGradientElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 public:
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedLength> Cx();
   already_AddRefed<SVGAnimatedLength> Cy();
   already_AddRefed<SVGAnimatedLength> R();
   already_AddRefed<SVGAnimatedLength> Fx();
   already_AddRefed<SVGAnimatedLength> Fy();
 protected:
--- a/dom/svg/SVGImageElement.cpp
+++ b/dom/svg/SVGImageElement.cpp
@@ -309,19 +309,19 @@ SVGImageElement::GetPreserveAspectRatio(
 nsSVGElement::StringAttributesInfo
 SVGImageElement::GetStringInfo()
 {
   return StringAttributesInfo(mStringAttributes, sStringInfo,
                               ArrayLength(sStringInfo));
 }
 
 nsresult
-SVGImageElement::CopyInnerTo(Element* aDest)
+SVGImageElement::CopyInnerTo(Element* aDest, bool aPreallocateChildren)
 {
   if (aDest->OwnerDoc()->IsStaticDocument()) {
     CreateStaticImageClone(static_cast<SVGImageElement*>(aDest));
   }
-  return SVGImageElementBase::CopyInnerTo(aDest);
+  return SVGImageElementBase::CopyInnerTo(aDest, aPreallocateChildren);
 }
 
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/svg/SVGImageElement.h
+++ b/dom/svg/SVGImageElement.h
@@ -60,19 +60,20 @@ public:
   virtual bool GetGeometryBounds(Rect* aBounds, const StrokeOptions& aStrokeOptions,
                                  const Matrix& aToBoundsSpace,
                                  const Matrix* aToNonScalingStrokeSpace = nullptr) override;
   virtual already_AddRefed<Path> BuildPath(PathBuilder* aBuilder) override;
 
   // nsSVGSVGElement methods:
   virtual bool HasValidDimensions() const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
-  nsresult CopyInnerTo(mozilla::dom::Element* aDest);
+  nsresult CopyInnerTo(mozilla::dom::Element* aDest, bool aPreallocateChildren);
 
   void MaybeLoadSVGImage();
 
   // WebIDL
   already_AddRefed<SVGAnimatedLength> X();
   already_AddRefed<SVGAnimatedLength> Y();
   already_AddRefed<SVGAnimatedLength> Width();
   already_AddRefed<SVGAnimatedLength> Height();
--- a/dom/svg/SVGLineElement.h
+++ b/dom/svg/SVGLineElement.h
@@ -38,17 +38,18 @@ public:
   virtual bool IsMarkable() override { return true; }
   virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks) override;
   virtual void GetAsSimplePath(SimplePath* aSimplePath) override;
   virtual already_AddRefed<Path> BuildPath(PathBuilder* aBuilder) override;
   virtual bool GetGeometryBounds(Rect* aBounds, const StrokeOptions& aStrokeOptions,
                                  const Matrix& aToBoundsSpace,
                                  const Matrix* aToNonScalingStrokeSpace = nullptr) override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedLength> X1();
   already_AddRefed<SVGAnimatedLength> Y1();
   already_AddRefed<SVGAnimatedLength> X2();
   already_AddRefed<SVGAnimatedLength> Y2();
 
 protected:
--- a/dom/svg/SVGMPathElement.h
+++ b/dom/svg/SVGMPathElement.h
@@ -37,17 +37,18 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SVGMPathElement,
                                            SVGMPathElementBase)
 
   NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
 
   // nsIContent interface
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
 
   virtual nsresult UnsetAttr(int32_t aNamespaceID, nsIAtom* aAttribute,
                              bool aNotify) override;
   // Element specializations
--- a/dom/svg/SVGMarkerElement.h
+++ b/dom/svg/SVGMarkerElement.h
@@ -122,17 +122,18 @@ public:
 
   // public helpers
   gfx::Matrix GetMarkerTransform(float aStrokeWidth,
                                  float aX, float aY, float aAutoAngle,
                                  bool aIsStart);
   nsSVGViewBoxRect GetViewBoxRect();
   gfx::Matrix GetViewBoxTransform();
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   nsSVGOrientType* GetOrientType() { return &mOrientType; }
 
   // Returns the value of svg.marker-improvements.enabled.
   static bool MarkerImprovementsPrefEnabled();
 
   // WebIDL
   already_AddRefed<SVGAnimatedRect> ViewBox();
--- a/dom/svg/SVGMaskElement.h
+++ b/dom/svg/SVGMaskElement.h
@@ -30,17 +30,18 @@ class SVGMaskElement final : public SVGM
 protected:
   friend nsresult (::NS_NewSVGMaskElement(nsIContent **aResult,
                                           already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
   explicit SVGMaskElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
   virtual JSObject* WrapNode(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
 
 public:
   // nsIContent interface
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
 
   // nsSVGSVGElement methods:
   virtual bool HasValidDimensions() const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedEnumeration> MaskUnits();
   already_AddRefed<SVGAnimatedEnumeration> MaskContentUnits();
--- a/dom/svg/SVGMetadataElement.h
+++ b/dom/svg/SVGMetadataElement.h
@@ -24,15 +24,16 @@ protected:
   friend nsresult (::NS_NewSVGMetadataElement(nsIContent **aResult,
                                               already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
   explicit SVGMetadataElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
   nsresult Init();
 
 public:
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_SVGMetadataElement_h
--- a/dom/svg/SVGPathElement.h
+++ b/dom/svg/SVGPathElement.h
@@ -53,17 +53,18 @@ public:
   /**
    * This returns a path without the extra little line segments that
    * ApproximateZeroLengthSubpathSquareCaps can insert if we have square-caps.
    * See the comment for that function for more info on that.
    */
   virtual already_AddRefed<Path> GetOrBuildPathForMeasuring() override;
 
   // nsIContent interface
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   virtual SVGAnimatedPathSegList* GetAnimPathSegList() override {
     return &mD;
   }
 
   virtual nsIAtom* GetPathDataAttrName() const override {
     return nsGkAtoms::d;
   }
--- a/dom/svg/SVGPatternElement.h
+++ b/dom/svg/SVGPatternElement.h
@@ -38,17 +38,18 @@ protected:
   virtual JSObject* WrapNode(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
 
 public:
   typedef mozilla::SVGAnimatedPreserveAspectRatio SVGAnimatedPreserveAspectRatio;
 
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* name) const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // nsSVGSVGElement methods:
   virtual bool HasValidDimensions() const override;
 
   virtual mozilla::nsSVGAnimatedTransformList*
     GetAnimatedTransformList(uint32_t aFlags = 0) override;
   virtual nsIAtom* GetTransformListAttrName() const override {
     return nsGkAtoms::patternTransform;
--- a/dom/svg/SVGPolygonElement.h
+++ b/dom/svg/SVGPolygonElement.h
@@ -26,15 +26,16 @@ protected:
   friend nsresult (::NS_NewSVGPolygonElement(nsIContent **aResult,
                                              already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
 
 public:
   // SVGGeometryElement methods:
   virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks) override;
   virtual already_AddRefed<Path> BuildPath(PathBuilder* aBuilder) override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_SVGPolygonElement_h
--- a/dom/svg/SVGPolylineElement.h
+++ b/dom/svg/SVGPolylineElement.h
@@ -25,15 +25,16 @@ protected:
   friend nsresult (::NS_NewSVGPolylineElement(nsIContent **aResult,
                                               already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
 
   // SVGGeometryElement methods:
   virtual already_AddRefed<Path> BuildPath(PathBuilder* aBuilder) override;
 
 public:
   // nsIContent interface
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_SVGPolylineElement_h
--- a/dom/svg/SVGRectElement.h
+++ b/dom/svg/SVGRectElement.h
@@ -32,17 +32,18 @@ public:
 
   // SVGGeometryElement methods:
   virtual bool GetGeometryBounds(Rect* aBounds, const StrokeOptions& aStrokeOptions,
                                  const Matrix& aToBoundsSpace,
                                  const Matrix* aToNonScalingStrokeSpace = nullptr) override;
   virtual void GetAsSimplePath(SimplePath* aSimplePath) override;
   virtual already_AddRefed<Path> BuildPath(PathBuilder* aBuilder = nullptr) override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedLength> X();
   already_AddRefed<SVGAnimatedLength> Y();
   already_AddRefed<SVGAnimatedLength> Height();
   already_AddRefed<SVGAnimatedLength> Width();
   already_AddRefed<SVGAnimatedLength> Rx();
   already_AddRefed<SVGAnimatedLength> Ry();
--- a/dom/svg/SVGSVGElement.cpp
+++ b/dom/svg/SVGSVGElement.cpp
@@ -187,25 +187,26 @@ SVGSVGElement::SVGSVGElement(already_Add
 {
 }
 
 //----------------------------------------------------------------------
 // nsIDOMNode methods
 
 // From NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGSVGElement)
 nsresult
-SVGSVGElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const
+SVGSVGElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                     bool aPreallocateChildren) const
 {
   *aResult = nullptr;
   already_AddRefed<mozilla::dom::NodeInfo> ni = RefPtr<mozilla::dom::NodeInfo>(aNodeInfo).forget();
   SVGSVGElement *it = new SVGSVGElement(ni, NOT_FROM_PARSER);
 
   nsCOMPtr<nsINode> kungFuDeathGrip = it;
   nsresult rv1 = it->Init();
-  nsresult rv2 = const_cast<SVGSVGElement*>(this)->CopyInnerTo(it);
+  nsresult rv2 = const_cast<SVGSVGElement*>(this)->CopyInnerTo(it, aPreallocateChildren);
   if (NS_SUCCEEDED(rv1) && NS_SUCCEEDED(rv2)) {
     kungFuDeathGrip.swap(*aResult);
   }
 
   return NS_FAILED(rv1) ? rv1 : rv2;
 }
 
 
--- a/dom/svg/SVGSVGElement.h
+++ b/dom/svg/SVGSVGElement.h
@@ -234,17 +234,18 @@ public:
    */
   void ChildrenOnlyTransformChanged(uint32_t aFlags = 0);
 
   // This services any pending notifications for the transform on on this root
   // <svg> node needing to be recalculated.  (Only applicable in
   // SVG-as-an-image documents.)
   virtual void FlushImageTransformInvalidation();
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // Returns true IFF our attributes are currently overridden by a <view>
   // element and that element's ID matches the passed-in string.
   bool IsOverriddenBy(const nsAString &aViewID) const {
     return mCurrentViewID && mCurrentViewID->Equals(aViewID);
   }
 
   svgFloatSize GetViewportSize() const {
--- a/dom/svg/SVGScriptElement.cpp
+++ b/dom/svg/SVGScriptElement.cpp
@@ -51,26 +51,27 @@ SVGScriptElement::SVGScriptElement(alrea
 SVGScriptElement::~SVGScriptElement()
 {
 }
 
 //----------------------------------------------------------------------
 // nsIDOMNode methods
 
 nsresult
-SVGScriptElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const
+SVGScriptElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                        bool aPreallocateChildren) const
 {
   *aResult = nullptr;
 
   already_AddRefed<mozilla::dom::NodeInfo> ni = RefPtr<mozilla::dom::NodeInfo>(aNodeInfo).forget();
   SVGScriptElement* it = new SVGScriptElement(ni, NOT_FROM_PARSER);
 
   nsCOMPtr<nsINode> kungFuDeathGrip = it;
   nsresult rv1 = it->Init();
-  nsresult rv2 = const_cast<SVGScriptElement*>(this)->CopyInnerTo(it);
+  nsresult rv2 = const_cast<SVGScriptElement*>(this)->CopyInnerTo(it, aPreallocateChildren);
   NS_ENSURE_SUCCESS(rv1, rv1);
   NS_ENSURE_SUCCESS(rv2, rv2);
 
   // The clone should be marked evaluated if we are.
   it->mAlreadyStarted = mAlreadyStarted;
   it->mLineNumber = mLineNumber;
   it->mMalformed = mMalformed;
 
--- a/dom/svg/SVGScriptElement.h
+++ b/dom/svg/SVGScriptElement.h
@@ -56,17 +56,18 @@ public:
                               bool aCompileEventHandlers) override;
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
                                 const nsAttrValue* aValue, bool aNotify) override;
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsIAtom* aAttribute,
                               const nsAString& aValue,
                               nsAttrValue& aResult) override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   void GetType(nsAString & aType);
   void SetType(const nsAString & aType, ErrorResult& rv);
   void GetCrossOrigin(nsAString & aCrossOrigin);
   void SetCrossOrigin(const nsAString & aCrossOrigin, ErrorResult& aError);
   already_AddRefed<SVGAnimatedString> Href();
 
--- a/dom/svg/SVGSetElement.h
+++ b/dom/svg/SVGSetElement.h
@@ -26,17 +26,18 @@ protected:
 
   friend nsresult (::NS_NewSVGSetElement(nsIContent **aResult,
                                          already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 public:
   // nsIDOMNode
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // SVGAnimationElement
   virtual nsSMILAnimationFunction& AnimationFunction() override;
 };
 
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/svg/SVGStopElement.h
+++ b/dom/svg/SVGStopElement.h
@@ -25,17 +25,18 @@ protected:
                                           already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
   explicit SVGStopElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 public:
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedNumber> Offset();
 
 protected:
 
   virtual NumberAttributesInfo GetNumberInfo() override;
   nsSVGNumber2 mOffset;
--- a/dom/svg/SVGStyleElement.h
+++ b/dom/svg/SVGStyleElement.h
@@ -54,17 +54,18 @@ public:
                            bool aNotify) override;
   virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
                              bool aNotify) override;
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsIAtom* aAttribute,
                               const nsAString& aValue,
                               nsAttrValue& aResult) override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // nsIMutationObserver
   NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
 
   // WebIDL
--- a/dom/svg/SVGSwitchElement.h
+++ b/dom/svg/SVGSwitchElement.h
@@ -42,17 +42,18 @@ public:
   // nsINode
   virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex,
                                  bool aNotify) override;
   virtual void RemoveChildAt(uint32_t aIndex, bool aNotify) override;
 
   // nsIContent
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 private:
   void UpdateActiveChild()
   { mActiveChild = FindActiveChild(); }
   nsIContent* FindActiveChild() const;
 
   // only this child will be displayed
   nsCOMPtr<nsIContent> mActiveChild;
 };
--- a/dom/svg/SVGSymbolElement.h
+++ b/dom/svg/SVGSymbolElement.h
@@ -33,17 +33,18 @@ protected:
 public:
   // interfaces:
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* name) const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedRect> ViewBox();
   already_AddRefed<DOMSVGAnimatedPreserveAspectRatio> PreserveAspectRatio();
 
   // SVGTests
   bool IsInChromeDoc() const override;
 
--- a/dom/svg/SVGTSpanElement.h
+++ b/dom/svg/SVGTSpanElement.h
@@ -24,17 +24,18 @@ protected:
                                            already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
   explicit SVGTSpanElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
   virtual JSObject* WrapNode(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
 
 public:
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
 protected:
   virtual EnumAttributesInfo GetEnumInfo() override;
   virtual LengthAttributesInfo GetLengthInfo() override;
 
   nsSVGEnum mEnumAttributes[1];
   virtual nsSVGEnum* EnumAttributes() override
     { return mEnumAttributes; }
--- a/dom/svg/SVGTextElement.h
+++ b/dom/svg/SVGTextElement.h
@@ -25,17 +25,18 @@ protected:
 
   friend nsresult (::NS_NewSVGTextElement(nsIContent **aResult,
                                           already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
 
 public:
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
 protected:
   virtual EnumAttributesInfo GetEnumInfo() override;
   virtual LengthAttributesInfo GetLengthInfo() override;
 
   nsSVGEnum mEnumAttributes[1];
   virtual nsSVGEnum* EnumAttributes() override
     { return mEnumAttributes; }
--- a/dom/svg/SVGTextPathElement.h
+++ b/dom/svg/SVGTextPathElement.h
@@ -41,17 +41,18 @@ protected:
                                               already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
   explicit SVGTextPathElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
   virtual JSObject* WrapNode(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
 
 public:
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedLength> StartOffset();
   already_AddRefed<SVGAnimatedEnumeration> Method();
   already_AddRefed<SVGAnimatedEnumeration> Spacing();
   already_AddRefed<SVGAnimatedString> Href();
 
  protected:
--- a/dom/svg/SVGTitleElement.h
+++ b/dom/svg/SVGTitleElement.h
@@ -35,17 +35,18 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIMutationObserver
   NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   virtual nsresult BindToTree(nsIDocument *aDocument, nsIContent *aParent,
                               nsIContent *aBindingParent,
                               bool aCompileEventHandlers) override;
 
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
 
--- a/dom/svg/SVGTransformableElement.h
+++ b/dom/svg/SVGTransformableElement.h
@@ -25,17 +25,18 @@ struct SVGBoundingBoxOptions;
 
 class SVGTransformableElement : public nsSVGElement
 {
 public:
   explicit SVGTransformableElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
     : nsSVGElement(aNodeInfo) {}
   virtual ~SVGTransformableElement() {}
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override = 0;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override = 0;
 
   // WebIDL
   already_AddRefed<SVGAnimatedTransformList> Transform();
   nsSVGElement* GetNearestViewportElement();
   nsSVGElement* GetFarthestViewportElement();
   already_AddRefed<SVGIRect> GetBBox(const SVGBoundingBoxOptions& aOptions, 
                                      ErrorResult& rv);
   already_AddRefed<SVGMatrix> GetCTM();
--- a/dom/svg/SVGUseElement.cpp
+++ b/dom/svg/SVGUseElement.cpp
@@ -84,25 +84,26 @@ SVGUseElement::~SVGUseElement()
 {
   UnlinkSource();
 }
 
 //----------------------------------------------------------------------
 // nsIDOMNode methods
 
 nsresult
-SVGUseElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const
+SVGUseElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                     bool aPreallocateChildren) const
 {
   *aResult = nullptr;
   already_AddRefed<mozilla::dom::NodeInfo> ni = RefPtr<mozilla::dom::NodeInfo>(aNodeInfo).forget();
   SVGUseElement *it = new SVGUseElement(ni);
 
   nsCOMPtr<nsINode> kungFuDeathGrip(it);
   nsresult rv1 = it->Init();
-  nsresult rv2 = const_cast<SVGUseElement*>(this)->CopyInnerTo(it);
+  nsresult rv2 = const_cast<SVGUseElement*>(this)->CopyInnerTo(it, aPreallocateChildren);
 
   // SVGUseElement specific portion - record who we cloned from
   it->mOriginal = const_cast<SVGUseElement*>(this);
 
   if (NS_SUCCEEDED(rv1) && NS_SUCCEEDED(rv2)) {
     kungFuDeathGrip.swap(*aResult);
   }
 
--- a/dom/svg/SVGUseElement.h
+++ b/dom/svg/SVGUseElement.h
@@ -63,17 +63,18 @@ public:
 
   // nsSVGElement specializations:
   virtual gfxMatrix PrependLocalTransformsTo(
     const gfxMatrix &aMatrix,
     SVGTransformTypes aWhich = eAllTransforms) const override;
   virtual bool HasValidDimensions() const override;
 
   // nsIContent interface
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedString> Href();
   already_AddRefed<SVGAnimatedLength> X();
   already_AddRefed<SVGAnimatedLength> Y();
   already_AddRefed<SVGAnimatedLength> Width();
   already_AddRefed<SVGAnimatedLength> Height();
--- a/dom/svg/SVGViewElement.h
+++ b/dom/svg/SVGViewElement.h
@@ -37,17 +37,18 @@ protected:
   friend class SVGSVGElement;
   friend class ::nsSVGOuterSVGFrame;
   explicit SVGViewElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
   friend nsresult (::NS_NewSVGViewElement(nsIContent **aResult,
                                           already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
   virtual JSObject* WrapNode(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
 
 public:
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   // WebIDL
   uint16_t ZoomAndPan() { return mEnumAttributes[ZOOMANDPAN].GetAnimValue(); }
   void SetZoomAndPan(uint16_t aZoomAndPan, ErrorResult& rv);
   already_AddRefed<SVGAnimatedRect> ViewBox();
   already_AddRefed<DOMSVGAnimatedPreserveAspectRatio> PreserveAspectRatio();
   already_AddRefed<DOMSVGStringList> ViewTarget();
 
--- a/dom/svg/nsSVGElement.h
+++ b/dom/svg/nsSVGElement.h
@@ -78,17 +78,18 @@ protected:
   explicit nsSVGElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
   friend nsresult NS_NewSVGElement(mozilla::dom::Element **aResult,
                                    already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
   nsresult Init();
   virtual ~nsSVGElement();
 
 public:
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_MUST_OVERRIDE override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const MOZ_MUST_OVERRIDE override;
 
   typedef mozilla::SVGNumberList SVGNumberList;
   typedef mozilla::SVGAnimatedNumberList SVGAnimatedNumberList;
   typedef mozilla::SVGUserUnitList SVGUserUnitList;
   typedef mozilla::SVGAnimatedLengthList SVGAnimatedLengthList;
   typedef mozilla::SVGAnimatedPointList SVGAnimatedPointList;
   typedef mozilla::SVGAnimatedPathSegList SVGAnimatedPathSegList;
   typedef mozilla::SVGAnimatedPreserveAspectRatio SVGAnimatedPreserveAspectRatio;
--- a/dom/svg/nsSVGFilters.h
+++ b/dom/svg/nsSVGFilters.h
@@ -77,17 +77,18 @@ public:
 
   // interfaces:
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
 
   // nsSVGElement interface
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override = 0;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override = 0;
 
   virtual bool HasValidDimensions() const override;
 
   bool IsNodeOfType(uint32_t aFlags) const override
     { return !(aFlags & ~(eCONTENT | eFILTER)); }
 
   virtual nsSVGString& GetResultImageName() = 0;
   // Return a list of all image names used as sources. Default is to
@@ -154,17 +155,18 @@ typedef nsSVGElement SVGFEUnstyledElemen
 
 class SVGFEUnstyledElement : public SVGFEUnstyledElementBase
 {
 protected:
   explicit SVGFEUnstyledElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
     : SVGFEUnstyledElementBase(aNodeInfo) {}
 
 public:
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override = 0;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override = 0;
 
   // returns true if changes to the attribute should cause us to
   // repaint the filter
   virtual bool AttributeAffectsRendering(
           int32_t aNameSpaceID, nsIAtom* aAttribute) const = 0;
 };
 
 //------------------------------------------------------------
--- a/dom/xbl/XBLChildrenElement.h
+++ b/dom/xbl/XBLChildrenElement.h
@@ -28,17 +28,18 @@ public:
     : nsXMLElement(aNodeInfo)
   {
   }
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsINode interface methods
-  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
+                         bool aPreallocateChildren) const override;
 
   virtual nsIDOMNode* AsDOMNode() override { return this; }
 
   // nsIContent interface methods
   virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
                              bool aNotify) override;
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsIAtom* aAttribute,
--- a/dom/xml/XMLDocument.cpp
+++ b/dom/xml/XMLDocument.cpp
@@ -602,23 +602,24 @@ XMLDocument::EndLoad()
 XMLDocument::DocAddSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
 {
   nsDocument::DocAddSizeOfExcludingThis(aWindowSizes);
 }
 
 // nsIDOMDocument interface
 
 nsresult
-XMLDocument::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const
+XMLDocument::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                   bool aPreallocateChildren) const
 {
   NS_ASSERTION(aNodeInfo->NodeInfoManager() == mNodeInfoManager,
                "Can't import this document into another document!");
 
   RefPtr<XMLDocument> clone = new XMLDocument();
-  nsresult rv = CloneDocHelper(clone);
+  nsresult rv = CloneDocHelper(clone, aPreallocateChildren);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // State from XMLDocument
   clone->mAsync = mAsync;
   clone->mIsPlainDocument = mIsPlainDocument;
 
   return CallQueryInterface(clone.get(), aResult);
 }
--- a/dom/xml/XMLDocument.h
+++ b/dom/xml/XMLDocument.h
@@ -46,17 +46,18 @@ public:
 
   virtual void EndLoad() override;
 
   // nsIDOMXMLDocument
   NS_DECL_NSIDOMXMLDOCUMENT
 
   virtual nsresult Init() override;
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   virtual void DocAddSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const override;
   // DocAddSizeOfIncludingThis is inherited from nsIDocument.
 
 
   // WebIDL API
   bool Load(const nsAString& aUrl, CallerType aCallerType, ErrorResult& aRv);
   bool Async() const
--- a/dom/xml/nsXMLElement.h
+++ b/dom/xml/nsXMLElement.h
@@ -26,17 +26,18 @@ public:
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   // nsINode interface methods
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                         bool aPreallocateChildren) const override;
 
   virtual nsIDOMNode* AsDOMNode() override { return this; }
 
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
 
 protected:
   virtual ~nsXMLElement() {}
--- a/dom/xul/XULDocument.cpp
+++ b/dom/xul/XULDocument.cpp
@@ -1867,17 +1867,18 @@ XULDocument::RemoveElementFromRefMap(Ele
 }
 
 //----------------------------------------------------------------------
 //
 // nsIDOMNode interface
 //
 
 nsresult
-XULDocument::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const
+XULDocument::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                   bool aPreallocateChildren) const
 {
     // We don't allow cloning of a XUL document
     *aResult = nullptr;
     return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
 }
 
 
 //----------------------------------------------------------------------
--- a/dom/xul/XULDocument.h
+++ b/dom/xul/XULDocument.h
@@ -133,17 +133,18 @@ public:
     NS_IMETHOD SetTemplateBuilderFor(nsIContent* aContent,
                                      nsIXULTemplateBuilder* aBuilder) override;
     NS_IMETHOD GetTemplateBuilderFor(nsIContent* aContent,
                                      nsIXULTemplateBuilder** aResult) override;
     NS_IMETHOD OnPrototypeLoadDone(bool aResumeWalk) override;
     bool OnDocumentParserError() override;
 
     // nsINode interface overrides
-    virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+    virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                           bool aPreallocateChildren) const override;
 
     // nsIDOMNode interface
     NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
     // nsIDOMDocument interface
     using nsDocument::CreateElement;
     using nsDocument::CreateElementNS;
     NS_FORWARD_NSIDOMDOCUMENT(XMLDocument::)
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -352,32 +352,37 @@ NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION
     NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIFrameLoaderOwner,
                                    new nsXULElementTearoff(this))
 NS_INTERFACE_MAP_END_INHERITING(nsStyledElement)
 
 //----------------------------------------------------------------------
 // nsIDOMNode interface
 
 nsresult
-nsXULElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const
+nsXULElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                    bool aPreallocateChildren) const
 {
     *aResult = nullptr;
 
     RefPtr<mozilla::dom::NodeInfo> ni = aNodeInfo;
     RefPtr<nsXULElement> element = new nsXULElement(ni.forget());
 
+    nsresult rv = element->mAttrsAndChildren.EnsureCapacityToClone(mAttrsAndChildren,
+                                                                   aPreallocateChildren);
+    NS_ENSURE_SUCCESS(rv, rv);
+
     // XXX TODO: set up RDF generic builder n' stuff if there is a
     // 'datasources' attribute? This is really kind of tricky,
     // because then we'd need to -selectively- copy children that
     // -weren't- generated from RDF. Ugh. Forget it.
 
     // Note that we're _not_ copying mControllers.
 
     uint32_t count = mAttrsAndChildren.AttrCount();
-    nsresult rv = NS_OK;
+    rv = NS_OK;
     for (uint32_t i = 0; i < count; ++i) {
         const nsAttrName* originalName = mAttrsAndChildren.AttrNameAt(i);
         const nsAttrValue* originalValue = mAttrsAndChildren.AttrAt(i);
         nsAttrValue attrValue;
 
         // Style rules need to be cloned.
         if (originalValue->Type() == nsAttrValue::eCSSDeclaration) {
             DeclarationBlock* decl = originalValue->GetCSSDeclarationValue();
--- a/dom/xul/nsXULElement.h
+++ b/dom/xul/nsXULElement.h
@@ -409,17 +409,18 @@ public:
     using nsStyledElement::GetParentElement;
 
     // nsIDOMElement
     NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
     // nsIDOMXULElement
     NS_DECL_NSIDOMXULELEMENT
 
-    virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
+    virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
+                           bool aPreallocateChildren) const override;
     virtual mozilla::EventStates IntrinsicState() const override;
 
     nsresult GetFrameLoaderXPCOM(nsIFrameLoader** aFrameLoader);
     void PresetOpenerWindow(mozIDOMWindowProxy* aWindow, ErrorResult& aRv);
     nsresult SetIsPrerendered();
 
     virtual void RecompileScriptEventListeners() override;