Bug 1064211 - Keep CustomElementData alive while on processing stack. r=mrbkap
--- 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: