/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_dom_CustomElementRegistry_h #define mozilla_dom_CustomElementRegistry_h #include "js/GCHashTable.h" #include "js/TypeDecls.h" #include "mozilla/Attributes.h" #include "mozilla/CycleCollectedJSContext.h" // for MicroTaskRunnable #include "mozilla/dom/BindingDeclarations.h" #include "mozilla/dom/CustomElementRegistryBinding.h" #include "mozilla/dom/Document.h" #include "mozilla/dom/Element.h" #include "mozilla/dom/ElementInternals.h" #include "mozilla/dom/ElementInternalsBinding.h" #include "mozilla/dom/HTMLFormElement.h" #include "mozilla/RefPtr.h" #include "nsCycleCollectionParticipant.h" #include "nsWrapperCache.h" #include "nsTHashSet.h" #include "nsAtomHashKeys.h" namespace mozilla { class ErrorResult; namespace dom { struct CustomElementData; struct ElementDefinitionOptions; class CallbackFunction; class CustomElementCallback; class CustomElementReaction; class DocGroup; class Promise; enum class ElementCallbackType { eConnected, eDisconnected, eAdopted, eAttributeChanged, eFormAssociated, eFormReset, eFormDisabled, eFormStateRestore, eGetCustomInterface }; struct LifecycleCallbackArgs { // Used by the attribute changed callback. RefPtr mName; nsString mOldValue; nsString mNewValue; nsString mNamespaceURI; // Used by the adopted callback. RefPtr mOldDocument; RefPtr mNewDocument; // Used by the form associated callback. RefPtr mForm; // Used by the form disabled callback. bool mDisabled; // Used by the form state restore callback. Nullable mState; RestoreReason mReason; size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const; }; // Each custom element has an associated callback queue and an element is // being created flag. struct 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, ePrecustomized }; explicit CustomElementData(nsAtom* aType); CustomElementData(nsAtom* aType, State aState); ~CustomElementData() = default; // Custom element state as described in the custom element spec. State mState; // custom element reaction queue as described in the custom element spec. // There is 1 reaction in reaction queue, when 1) it becomes disconnected, // 2) it’s adopted into a new document, 3) its attributes are changed, // appended, removed, or replaced. // There are 3 reactions in reaction queue when doing upgrade operation, // e.g., create an element, insert a node. AutoTArray, 3> mReactionQueue; void SetCustomElementDefinition(CustomElementDefinition* aDefinition); CustomElementDefinition* GetCustomElementDefinition() const; nsAtom* GetCustomElementType() const { return mType; } void AttachedInternals(); bool HasAttachedInternals() const { return mIsAttachedInternals; } bool IsFormAssociated() const; void Traverse(nsCycleCollectionTraversalCallback& aCb) const; void Unlink(); size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const; nsAtom* GetIs(const Element* aElement) const { // If mType isn't the same as name atom, this is a customized built-in // element, which has 'is' value set. return aElement->NodeInfo()->NameAtom() == mType ? nullptr : mType.get(); } ElementInternals* GetElementInternals() const { return mElementInternals; } ElementInternals* GetOrCreateElementInternals(HTMLElement* aTarget) { if (!mElementInternals) { mElementInternals = MakeAndAddRef(aTarget); } return mElementInternals; } private: // Custom element type, for