summaryrefslogtreecommitdiff
path: root/dom
diff options
context:
space:
mode:
authorGaming4JC <g4jc@hyperbola.info>2020-01-05 15:31:44 -0500
committerGaming4JC <g4jc@hyperbola.info>2020-01-26 15:50:27 -0500
commit8573c572fbf5fa68defb3228e7f1450ec234d59b (patch)
tree97c6eefe6718d62d901155eca3badbfec67eebb0 /dom
parentf50503df9c2eced785957626273ee07e5312d546 (diff)
downloaduxp-8573c572fbf5fa68defb3228e7f1450ec234d59b.tar.gz
Bug 1392970 - Part 1: Make CustomElementDefinition ref-counted and put it in CustomElementData.
Tag UXP Issue #1344
Diffstat (limited to 'dom')
-rw-r--r--dom/base/CustomElementRegistry.cpp109
-rw-r--r--dom/base/CustomElementRegistry.h27
-rw-r--r--dom/base/Element.cpp20
-rw-r--r--dom/base/Element.h16
-rw-r--r--dom/base/FragmentOrElement.cpp14
-rw-r--r--dom/base/nsDocument.cpp3
-rw-r--r--dom/bindings/BindingUtils.cpp2
7 files changed, 141 insertions, 50 deletions
diff --git a/dom/base/CustomElementRegistry.cpp b/dom/base/CustomElementRegistry.cpp
index 27e92a56a5..b752fdda72 100644
--- a/dom/base/CustomElementRegistry.cpp
+++ b/dom/base/CustomElementRegistry.cpp
@@ -160,46 +160,15 @@ private:
NS_IMPL_CYCLE_COLLECTION_CLASS(CustomElementRegistry)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CustomElementRegistry)
- tmp->mCustomDefinitions.Clear();
tmp->mConstructors.clear();
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mCustomDefinitions)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWhenDefinedPromiseMap)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CustomElementRegistry)
- for (auto iter = tmp->mCustomDefinitions.Iter(); !iter.Done(); iter.Next()) {
- auto& callbacks = iter.UserData()->mCallbacks;
-
- if (callbacks->mAttributeChangedCallback.WasPassed()) {
- NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
- "mCustomDefinitions->mCallbacks->mAttributeChangedCallback");
- cb.NoteXPCOMChild(callbacks->mAttributeChangedCallback.Value());
- }
-
- if (callbacks->mCreatedCallback.WasPassed()) {
- NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
- "mCustomDefinitions->mCallbacks->mCreatedCallback");
- cb.NoteXPCOMChild(callbacks->mCreatedCallback.Value());
- }
-
- if (callbacks->mAttachedCallback.WasPassed()) {
- NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
- "mCustomDefinitions->mCallbacks->mAttachedCallback");
- cb.NoteXPCOMChild(callbacks->mAttachedCallback.Value());
- }
-
- if (callbacks->mDetachedCallback.WasPassed()) {
- NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
- "mCustomDefinitions->mCallbacks->mDetachedCallback");
- cb.NoteXPCOMChild(callbacks->mDetachedCallback.Value());
- }
-
- NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
- "mCustomDefinitions->mConstructor");
- cb.NoteXPCOMChild(iter.UserData()->mConstructor);
- }
-
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCustomDefinitions)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWhenDefinedPromiseMap)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@@ -256,7 +225,7 @@ CustomElementRegistry::LookupCustomElementDefinition(const nsAString& aLocalName
nsCOMPtr<nsIAtom> localNameAtom = NS_Atomize(aLocalName);
nsCOMPtr<nsIAtom> typeAtom = aIs ? NS_Atomize(*aIs) : localNameAtom;
- CustomElementDefinition* data = mCustomDefinitions.Get(typeAtom);
+ CustomElementDefinition* data = mCustomDefinitions.GetWeak(typeAtom);
if (data && data->mLocalName == localNameAtom) {
return data;
}
@@ -275,7 +244,7 @@ CustomElementRegistry::LookupCustomElementDefinition(JSContext* aCx,
return nullptr;
}
- CustomElementDefinition* definition = mCustomDefinitions.Get(ptr->value());
+ CustomElementDefinition* definition = mCustomDefinitions.GetWeak(ptr->value());
MOZ_ASSERT(definition, "Definition must be found in mCustomDefinitions");
return definition;
@@ -294,7 +263,7 @@ CustomElementRegistry::RegisterUnresolvedElement(Element* aElement, nsIAtom* aTy
typeName = info->NameAtom();
}
- if (mCustomDefinitions.Get(typeName)) {
+ if (mCustomDefinitions.GetWeak(typeName)) {
return;
}
@@ -368,7 +337,7 @@ CustomElementRegistry::CreateCustomElementCallback(
nsCOMPtr<nsIAtom> typeAtom = elementData ?
elementData->mType.get() : info->NameAtom();
- definition = mCustomDefinitions.Get(typeAtom);
+ definition = mCustomDefinitions.GetWeak(typeAtom);
if (!definition || definition->mLocalName != info->NameAtom()) {
// Trying to enqueue a callback for an element that is not
// a custom element. We are done, nothing to do.
@@ -447,7 +416,7 @@ CustomElementRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType
nsCOMPtr<nsIAtom> typeAtom = elementData ?
elementData->mType.get() : info->NameAtom();
- definition = mCustomDefinitions.Get(typeAtom);
+ definition = mCustomDefinitions.GetWeak(typeAtom);
if (!definition || definition->mLocalName != info->NameAtom()) {
return;
}
@@ -482,7 +451,8 @@ void
CustomElementRegistry::GetCustomPrototype(nsIAtom* aAtom,
JS::MutableHandle<JSObject*> aPrototype)
{
- mozilla::dom::CustomElementDefinition* definition = mCustomDefinitions.Get(aAtom);
+ mozilla::dom::CustomElementDefinition* definition =
+ mCustomDefinitions.GetWeak(aAtom);
if (definition) {
aPrototype.set(definition->mPrototype);
} else {
@@ -617,7 +587,7 @@ CustomElementRegistry::Define(const nsAString& aName,
* 3. If this CustomElementRegistry contains an entry with name name, then
* throw a "NotSupportedError" DOMException and abort these steps.
*/
- if (mCustomDefinitions.Get(nameAtom)) {
+ if (mCustomDefinitions.GetWeak(nameAtom)) {
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return;
}
@@ -628,7 +598,7 @@ CustomElementRegistry::Define(const nsAString& aName,
*/
const auto& ptr = mConstructors.lookup(constructorUnwrapped);
if (ptr) {
- MOZ_ASSERT(mCustomDefinitions.Get(ptr->value()),
+ MOZ_ASSERT(mCustomDefinitions.GetWeak(ptr->value()),
"Definition must be found in mCustomDefinitions");
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return;
@@ -826,7 +796,7 @@ CustomElementRegistry::Define(const nsAString& aName,
return;
}
- CustomElementDefinition* definition =
+ RefPtr<CustomElementDefinition> definition =
new CustomElementDefinition(nameAtom,
localNameAtom,
&aFunctionConstructor,
@@ -835,7 +805,8 @@ CustomElementRegistry::Define(const nsAString& aName,
callbacks,
0 /* TODO dependent on HTML imports. Bug 877072 */);
- mCustomDefinitions.Put(nameAtom, definition);
+ CustomElementDefinition* def = definition.get();
+ mCustomDefinitions.Put(nameAtom, definition.forget());
MOZ_ASSERT(mCustomDefinitions.Count() == mConstructors.count(),
"Number of entries should be the same");
@@ -843,7 +814,7 @@ CustomElementRegistry::Define(const nsAString& aName,
/**
* 13. 14. 15. Upgrade candidates
*/
- UpgradeCandidates(nameAtom, definition, aRv);
+ UpgradeCandidates(nameAtom, def, aRv);
/**
* 16. If this CustomElementRegistry's when-defined promise map contains an
@@ -866,7 +837,7 @@ CustomElementRegistry::Get(JSContext* aCx, const nsAString& aName,
JS::MutableHandle<JS::Value> aRetVal)
{
nsCOMPtr<nsIAtom> nameAtom(NS_Atomize(aName));
- CustomElementDefinition* data = mCustomDefinitions.Get(nameAtom);
+ CustomElementDefinition* data = mCustomDefinitions.GetWeak(nameAtom);
if (!data) {
aRetVal.setUndefined();
@@ -893,7 +864,7 @@ CustomElementRegistry::WhenDefined(const nsAString& aName, ErrorResult& aRv)
return promise.forget();
}
- if (mCustomDefinitions.Get(nameAtom)) {
+ if (mCustomDefinitions.GetWeak(nameAtom)) {
promise->MaybeResolve(JS::UndefinedHandleValue);
return promise.forget();
}
@@ -996,6 +967,9 @@ CustomElementRegistry::Upgrade(Element* aElement,
// Step 8.
data->mState = CustomElementData::State::eCustom;
+ // Step 9.
+ aElement->SetCustomElementDefinition(aDefinition);
+
// This is for old spec.
nsContentUtils::EnqueueLifecycleCallback(aElement->OwnerDoc(),
nsIDocument::eCreated,
@@ -1148,6 +1122,49 @@ CustomElementReactionsStack::InvokeReactions(ElementQueue* aElementQueue,
//-----------------------------------------------------
// CustomElementDefinition
+NS_IMPL_CYCLE_COLLECTION_CLASS(CustomElementDefinition)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CustomElementDefinition)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mConstructor)
+ tmp->mPrototype = nullptr;
+ tmp->mCallbacks = nullptr;
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CustomElementDefinition)
+ mozilla::dom::LifecycleCallbacks* callbacks = tmp->mCallbacks.get();
+
+ if (callbacks->mAttributeChangedCallback.WasPassed()) {
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
+ "mCallbacks->mAttributeChangedCallback");
+ cb.NoteXPCOMChild(callbacks->mAttributeChangedCallback.Value());
+ }
+
+ if (callbacks->mCreatedCallback.WasPassed()) {
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCallbacks->mCreatedCallback");
+ cb.NoteXPCOMChild(callbacks->mCreatedCallback.Value());
+ }
+
+ if (callbacks->mAttachedCallback.WasPassed()) {
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCallbacks->mAttachedCallback");
+ cb.NoteXPCOMChild(callbacks->mAttachedCallback.Value());
+ }
+
+ if (callbacks->mDetachedCallback.WasPassed()) {
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCallbacks->mDetachedCallback");
+ cb.NoteXPCOMChild(callbacks->mDetachedCallback.Value());
+ }
+
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mConstructor");
+ cb.NoteXPCOMChild(tmp->mConstructor);
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(CustomElementDefinition)
+ NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mPrototype)
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(CustomElementDefinition, AddRef)
+NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(CustomElementDefinition, Release)
+
CustomElementDefinition::CustomElementDefinition(nsIAtom* aType,
nsIAtom* aLocalName,
Function* aConstructor,
diff --git a/dom/base/CustomElementRegistry.h b/dom/base/CustomElementRegistry.h
index b731a18588..89e7543657 100644
--- a/dom/base/CustomElementRegistry.h
+++ b/dom/base/CustomElementRegistry.h
@@ -13,7 +13,9 @@
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/FunctionBinding.h"
+#include "mozilla/dom/WebComponentsBinding.h"
#include "nsCycleCollectionParticipant.h"
+#include "nsGenericHTMLElement.h"
#include "nsWrapperCache.h"
class nsDocument;
@@ -23,7 +25,6 @@ namespace dom {
struct CustomElementData;
struct ElementDefinitionOptions;
-struct LifecycleCallbacks;
class CallbackFunction;
class CustomElementReaction;
class Function;
@@ -115,6 +116,22 @@ struct CustomElementData
// e.g., create an element, insert a node.
AutoTArray<UniquePtr<CustomElementReaction>, 3> mReactionQueue;
+ RefPtr<CustomElementDefinition> mCustomElementDefinition;
+
+ void
+ SetCustomElementDefinition(CustomElementDefinition* aDefinition)
+ {
+ MOZ_ASSERT(!mCustomElementDefinition);
+
+ mCustomElementDefinition = aDefinition;
+ }
+
+ CustomElementDefinition*
+ GetCustomElementDefinition()
+ {
+ return mCustomElementDefinition;
+ }
+
private:
virtual ~CustomElementData() {}
};
@@ -125,6 +142,9 @@ private:
// https://html.spec.whatwg.org/multipage/scripting.html#custom-element-definition
struct CustomElementDefinition
{
+ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(CustomElementDefinition)
+ NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(CustomElementDefinition)
+
CustomElementDefinition(nsIAtom* aType,
nsIAtom* aLocalName,
Function* aConstructor,
@@ -170,6 +190,9 @@ struct CustomElementDefinition
return mObservedAttributes.Contains(aName);
}
+
+private:
+ ~CustomElementDefinition() {}
};
class CustomElementReaction
@@ -381,7 +404,7 @@ private:
CustomElementDefinition* aDefinition,
ErrorResult& aRv);
- typedef nsClassHashtable<nsISupportsHashKey, CustomElementDefinition>
+ typedef nsRefPtrHashtable<nsISupportsHashKey, CustomElementDefinition>
DefinitionMap;
typedef nsClassHashtable<nsISupportsHashKey, nsTArray<nsWeakPtr>>
CandidateMap;
diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp
index 5719b423d6..e90d444767 100644
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -4065,3 +4065,23 @@ Element::SetCustomElementData(CustomElementData* aData)
MOZ_ASSERT(!slots->mCustomElementData, "Custom element data may not be changed once set.");
slots->mCustomElementData = aData;
}
+
+CustomElementDefinition*
+Element::GetCustomElementDefinition() const
+{
+ CustomElementData* data = GetCustomElementData();
+ if (!data) {
+ return nullptr;
+ }
+
+ return data->GetCustomElementDefinition();
+}
+
+void
+Element::SetCustomElementDefinition(CustomElementDefinition* aDefinition)
+{
+ CustomElementData* data = GetCustomElementData();
+ MOZ_ASSERT(data);
+
+ data->SetCustomElementDefinition(aDefinition);
+}
diff --git a/dom/base/Element.h b/dom/base/Element.h
index e7218ee931..7820047034 100644
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -413,6 +413,22 @@ public:
*/
void SetCustomElementData(CustomElementData* aData);
+ /**
+ * Gets the custom element definition used by web components custom element.
+ *
+ * @return The custom element definition or null if element is not a custom
+ * element or custom element is not defined yet.
+ */
+ CustomElementDefinition* GetCustomElementDefinition() const;
+
+ /**
+ * Sets the custom element definition, called when custom element is created
+ * or upgraded.
+ *
+ * @param aDefinition The custom element definition.
+ */
+ void SetCustomElementDefinition(CustomElementDefinition* aDefinition);
+
protected:
/**
* Method to get the _intrinsic_ content state of this element. This is the
diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp
index e341ae315b..a851190ff6 100644
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -589,6 +589,13 @@ FragmentOrElement::nsDOMSlots::Traverse(nsCycleCollectionTraversalCallback &cb)
mExtendedSlots->mCustomElementData->mReactionQueue[i]->Traverse(cb);
}
}
+
+ if (mExtendedSlots->mCustomElementData->mCustomElementDefinition) {
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
+ "mExtendedSlots->mCustomElementData->mCustomElementDefinition");
+ cb.NoteNativeChild(mExtendedSlots->mCustomElementData->mCustomElementDefinition,
+ NS_CYCLE_COLLECTION_PARTICIPANT(CustomElementDefinition));
+ }
}
for (auto iter = mExtendedSlots->mRegisteredIntersectionObservers.Iter();
@@ -625,7 +632,12 @@ FragmentOrElement::nsDOMSlots::Unlink()
mExtendedSlots->mContainingShadow = nullptr;
MOZ_ASSERT(!(mExtendedSlots->mXBLBinding));
mExtendedSlots->mXBLInsertionParent = nullptr;
- mExtendedSlots->mCustomElementData = nullptr;
+ if (mExtendedSlots->mCustomElementData) {
+ if (mExtendedSlots->mCustomElementData->mCustomElementDefinition) {
+ mExtendedSlots->mCustomElementData->mCustomElementDefinition = nullptr;
+ }
+ mExtendedSlots->mCustomElementData = nullptr;
+ }
mExtendedSlots->mRegisteredIntersectionObservers.Clear();
nsCOMPtr<nsIFrameLoader> frameLoader =
do_QueryInterface(mExtendedSlots->mFrameLoaderOrOpener);
diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp
index 99f922c98b..6c97750b9a 100644
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -5673,7 +5673,8 @@ nsDocument::CustomElementConstructor(JSContext* aCx, unsigned aArgc, JS::Value*
}
nsCOMPtr<nsIAtom> typeAtom(NS_Atomize(elemName));
- CustomElementDefinition* definition = registry->mCustomDefinitions.Get(typeAtom);
+ CustomElementDefinition* definition =
+ registry->mCustomDefinitions.GetWeak(typeAtom);
if (!definition) {
return true;
}
diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp
index 3c31ec0e6e..f76f14d95f 100644
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -3554,6 +3554,8 @@ CreateHTMLElement(const GlobalObject& aGlobal, const JS::CallArgs& aCallArgs,
newElement->SetCustomElementData(
new CustomElementData(definition->mType, CustomElementData::State::eCustom));
+ newElement->SetCustomElementDefinition(definition);
+
return newElement.forget();
}