Bug 1064211 - Keep CustomElementData alive while on processing stack. r=mrbkap
authorWilliam Chen <wchen@mozilla.com>
Thu, 16 Oct 2014 11:53:36 -0700
changeset 210835 78c4d7d788d86574ac5635937f35ed12893b4958
parent 210834 c2d6b4070a933c424ed4642da6d74add31788c4c
child 210836 030d8d4684982327356a377cbb13c82b665ce992
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersmrbkap
bugs1064211
milestone36.0a1
Bug 1064211 - Keep CustomElementData alive while on processing stack. r=mrbkap
content/base/public/FragmentOrElement.h
content/base/src/nsDocument.cpp
content/base/src/nsDocument.h
--- a/content/base/public/FragmentOrElement.h
+++ b/content/base/public/FragmentOrElement.h
@@ -407,17 +407,17 @@ public:
     /**
      * XBL binding installed on the lement.
      */
     nsCOMPtr<nsIContent> mXBLInsertionParent;
 
     /**
      * Web components custom element data.
      */
-    nsAutoPtr<CustomElementData> mCustomElementData;
+    nsRefPtr<CustomElementData> mCustomElementData;
   };
 
 protected:
   void GetMarkup(bool aIncludeSelf, nsAString& aMarkup);
   void SetInnerHTMLInternal(const nsAString& aInnerHTML, ErrorResult& aError);
 
   // Override from nsINode
   virtual nsINode::nsSlots* CreateSlots() MOZ_OVERRIDE;
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -5839,22 +5839,17 @@ nsDocument::ProcessBaseElementQueue()
 }
 
 // static
 void
 nsDocument::ProcessTopElementQueue(bool aIsBaseQueue)
 {
   MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
 
-  if (sProcessingStack.isNothing()) {
-    // If XPCOM shutdown has reset the processing stack, don't do anything.
-    return;
-  }
-
-  nsTArray<CustomElementData*>& stack = *sProcessingStack;
+  nsTArray<nsRefPtr<CustomElementData>>& stack = *sProcessingStack;
   uint32_t firstQueue = stack.LastIndexOf((CustomElementData*) nullptr);
 
   if (aIsBaseQueue && firstQueue != 0) {
     return;
   }
 
   for (uint32_t i = firstQueue + 1; i < stack.Length(); ++i) {
     // Callback queue may have already been processed in an earlier
@@ -5881,17 +5876,17 @@ bool
 nsDocument::RegisterEnabled()
 {
   static bool sPrefValue =
     Preferences::GetBool("dom.webcomponents.enabled", false);
   return sPrefValue;
 }
 
 // static
-Maybe<nsTArray<mozilla::dom::CustomElementData*>>
+Maybe<nsTArray<nsRefPtr<mozilla::dom::CustomElementData>>>
 nsDocument::sProcessingStack;
 
 // static
 bool
 nsDocument::sProcessingBaseElementQueue;
 
 void
 nsDocument::RegisterElement(JSContext* aCx, const nsAString& aType,
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -320,16 +320,18 @@ private:
   // callback queue.
   CustomElementData* mOwnerData;
 };
 
 // Each custom element has an associated callback queue and an element is
 // being created flag.
 struct CustomElementData
 {
+  NS_INLINE_DECL_REFCOUNTING(CustomElementData)
+
   explicit CustomElementData(nsIAtom* aType);
   // Objects in this array are transient and empty after each microtask
   // checkpoint.
   nsTArray<nsAutoPtr<CustomElementCallback>> mCallbackQueue;
   // Custom element type, for <button is="x-button"> or <x-button>
   // this would be x-button.
   nsCOMPtr<nsIAtom> mType;
   // The callback that is next to be processed upon calling RunCallbackQueue.
@@ -341,16 +343,19 @@ struct CustomElementData
   bool mCreatedCallbackInvoked;
   // The microtask level associated with the callbacks in the callback queue,
   // it is used to determine if a new queue needs to be pushed onto the
   // processing stack.
   int32_t mAssociatedMicroTask;
 
   // Empties the callback queue.
   void RunCallbackQueue();
+
+private:
+  virtual ~CustomElementData() {}
 };
 
 // The required information for a custom element as defined in:
 // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html
 struct CustomElementDefinition
 {
   CustomElementDefinition(JSObject* aPrototype,
                           nsIAtom* aType,
@@ -1515,17 +1520,17 @@ protected:
 
 private:
   // Array representing the processing stack in the custom elements
   // specification. The processing stack is conceptually a stack of
   // element queues. Each queue is represented by a sequence of
   // CustomElementData in this array, separated by nullptr that
   // represent the boundaries of the items in the stack. The first
   // queue in the stack is the base element queue.
-  static mozilla::Maybe<nsTArray<mozilla::dom::CustomElementData*>> sProcessingStack;
+  static mozilla::Maybe<nsTArray<nsRefPtr<mozilla::dom::CustomElementData>>> sProcessingStack;
 
   // Flag to prevent re-entrance into base element queue as described in the
   // custom elements speicification.
   static bool sProcessingBaseElementQueue;
 
   static bool CustomElementConstructor(JSContext* aCx, unsigned aArgc, JS::Value* aVp);
 
 public: