mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-29 11:57:32 +09:00
Bug 1392970 - Part 1: Make CustomElementDefinition ref-counted and put it in CustomElementData.
Tag UXP Issue #1344
This commit is contained in:
parent
b0285ef3f7
commit
7ce1742985
7 changed files with 141 additions and 50 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue