diff options
-rw-r--r-- | dom/base/CustomElementRegistry.cpp | 50 | ||||
-rw-r--r-- | dom/base/CustomElementRegistry.h | 13 | ||||
-rw-r--r-- | dom/bindings/BindingUtils.cpp | 3 |
3 files changed, 44 insertions, 22 deletions
diff --git a/dom/base/CustomElementRegistry.cpp b/dom/base/CustomElementRegistry.cpp index 75477dbaa..6c643d861 100644 --- a/dom/base/CustomElementRegistry.cpp +++ b/dom/base/CustomElementRegistry.cpp @@ -78,12 +78,21 @@ CustomElementCallback::CustomElementCallback(Element* aThisObject, { } +//----------------------------------------------------- +// CustomElementData + CustomElementData::CustomElementData(nsIAtom* aType) - : mType(aType), - mCurrentCallback(-1), - mElementIsBeingCreated(false), - mCreatedCallbackInvoked(true), - mAssociatedMicroTask(-1) + : CustomElementData(aType, CustomElementData::State::eUndefined) +{ +} + +CustomElementData::CustomElementData(nsIAtom* aType, State aState) + : mType(aType) + , mCurrentCallback(-1) + , mElementIsBeingCreated(false) + , mCreatedCallbackInvoked(true) + , mAssociatedMicroTask(-1) + , mState(aState) { } @@ -99,6 +108,9 @@ CustomElementData::RunCallbackQueue() mCurrentCallback = -1; } +//----------------------------------------------------- +// CustomElementRegistry + // Only needed for refcounted objects. NS_IMPL_CYCLE_COLLECTION_CLASS(CustomElementRegistry) @@ -305,10 +317,15 @@ CustomElementRegistry::SetupCustomElement(Element* aElement, aElement->SetAttr(kNameSpaceID_None, nsGkAtoms::is, *aTypeExtension, true); } - CustomElementDefinition* data = LookupCustomElementDefinition( + // SetupCustomElement() should be called with an element that don't have + // CustomElementData setup, if not we will hit the assertion in + // SetCustomElementData(). + aElement->SetCustomElementData(new CustomElementData(typeAtom)); + + CustomElementDefinition* definition = LookupCustomElementDefinition( aElement->NodeInfo()->LocalName(), aTypeExtension); - if (!data) { + if (!definition) { // The type extension doesn't exist in the registry, // thus we don't need to enqueue callback or adjust // the "is" attribute, but it is possibly an upgrade candidate. @@ -316,7 +333,7 @@ CustomElementRegistry::SetupCustomElement(Element* aElement, return; } - if (data->mLocalName != tagAtom) { + if (definition->mLocalName != tagAtom) { // The element doesn't match the local name for the // definition, thus the element isn't a custom element // and we don't need to do anything more. @@ -325,7 +342,7 @@ CustomElementRegistry::SetupCustomElement(Element* aElement, // Enqueuing the created callback will set the CustomElementData on the // element, causing prototype swizzling to occur in Element::WrapObject. - EnqueueLifecycleCallback(nsIDocument::eCreated, aElement, nullptr, data); + EnqueueLifecycleCallback(nsIDocument::eCreated, aElement, nullptr, definition); } void @@ -334,7 +351,8 @@ CustomElementRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType LifecycleCallbackArgs* aArgs, CustomElementDefinition* aDefinition) { - CustomElementData* elementData = aCustomElement->GetCustomElementData(); + RefPtr<CustomElementData> elementData = aCustomElement->GetCustomElementData(); + MOZ_ASSERT(elementData, "CustomElementData should exist"); // Let DEFINITION be ELEMENT's definition CustomElementDefinition* definition = aDefinition; @@ -354,16 +372,6 @@ CustomElementRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType } } - if (!elementData) { - // Create the custom element data the first time - // that we try to enqueue a callback. - elementData = new CustomElementData(definition->mType); - // aCustomElement takes ownership of elementData - aCustomElement->SetCustomElementData(elementData); - MOZ_ASSERT(aType == nsIDocument::eCreated, - "First callback should be the created callback"); - } - // Let CALLBACK be the callback associated with the key NAME in CALLBACKS. CallbackFunction* func = nullptr; switch (aType) { @@ -881,8 +889,6 @@ CustomElementRegistry::Upgrade(Element* aElement, } } // Leave prototype's compartment. - // Enqueuing the created callback will set the CustomElementData on the - // element, causing prototype swizzling to occur in Element::WrapObject. EnqueueLifecycleCallback(nsIDocument::eCreated, aElement, nullptr, aDefinition); } diff --git a/dom/base/CustomElementRegistry.h b/dom/base/CustomElementRegistry.h index 24d501d73..6184c0ac3 100644 --- a/dom/base/CustomElementRegistry.h +++ b/dom/base/CustomElementRegistry.h @@ -71,7 +71,18 @@ struct CustomElementData { NS_INLINE_DECL_REFCOUNTING(CustomElementData) + // https://dom.spec.whatwg.org/#concept-element-custom-element-state + // CustomElementData is only created on the element which is a custom element + // or an upgrade candidate, so the state of an element without + // CustomElementData is "uncustomized". + enum class State { + eUndefined, + eFailed, + eCustom + }; + explicit CustomElementData(nsIAtom* aType); + CustomElementData(nsIAtom* aType, State aState); // Objects in this array are transient and empty after each microtask // checkpoint. nsTArray<nsAutoPtr<CustomElementCallback>> mCallbackQueue; @@ -89,6 +100,8 @@ struct CustomElementData // it is used to determine if a new queue needs to be pushed onto the // processing stack. int32_t mAssociatedMicroTask; + // Custom element state as described in the custom element spec. + State mState; // Empties the callback queue. void RunCallbackQueue(); diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp index c6452501a..6c35da05e 100644 --- a/dom/bindings/BindingUtils.cpp +++ b/dom/bindings/BindingUtils.cpp @@ -3550,6 +3550,9 @@ CreateHTMLElement(const GlobalObject& aGlobal, const JS::CallArgs& aCallArgs, element = CreateHTMLElement(tag, nodeInfo.forget(), NOT_FROM_PARSER); } + element->SetCustomElementData( + new CustomElementData(definition->mType, CustomElementData::State::eCustom)); + return element.forget(); } |