LCOV - code coverage report
Current view: top level - dom/base - CustomElementRegistry.h (source / functions) Hit Total Coverage
Test: output.info Lines: 22 55 40.0 %
Date: 2018-08-07 16:42:27 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef mozilla_dom_CustomElementRegistry_h
       8             : #define mozilla_dom_CustomElementRegistry_h
       9             : 
      10             : #include "js/GCHashTable.h"
      11             : #include "js/TypeDecls.h"
      12             : #include "mozilla/Attributes.h"
      13             : #include "mozilla/CycleCollectedJSContext.h" // for MicroTaskRunnable
      14             : #include "mozilla/ErrorResult.h"
      15             : #include "mozilla/dom/BindingDeclarations.h"
      16             : #include "mozilla/dom/CustomElementRegistryBinding.h"
      17             : #include "mozilla/dom/Element.h"
      18             : #include "mozilla/dom/FunctionBinding.h"
      19             : #include "mozilla/dom/WebComponentsBinding.h"
      20             : #include "nsCycleCollectionParticipant.h"
      21             : #include "nsGenericHTMLElement.h"
      22             : #include "nsWrapperCache.h"
      23             : #include "nsContentUtils.h"
      24             : 
      25             : class nsDocument;
      26             : 
      27             : namespace mozilla {
      28             : namespace dom {
      29             : 
      30             : struct CustomElementData;
      31             : struct ElementDefinitionOptions;
      32             : class CallbackFunction;
      33             : class CustomElementReaction;
      34             : class DocGroup;
      35             : class Function;
      36             : class Promise;
      37             : 
      38           0 : struct LifecycleCallbackArgs
      39             : {
      40             :   nsString name;
      41             :   nsString oldValue;
      42             :   nsString newValue;
      43             :   nsString namespaceURI;
      44             : };
      45             : 
      46             : struct LifecycleAdoptedCallbackArgs
      47             : {
      48             :   nsCOMPtr<nsIDocument> mOldDocument;
      49             :   nsCOMPtr<nsIDocument> mNewDocument;
      50             : };
      51             : 
      52             : class CustomElementCallback
      53             : {
      54             : public:
      55             :   CustomElementCallback(Element* aThisObject,
      56             :                         nsIDocument::ElementCallbackType aCallbackType,
      57             :                         CallbackFunction* aCallback);
      58             :   void Traverse(nsCycleCollectionTraversalCallback& aCb) const;
      59             :   void Call();
      60             :   void SetArgs(LifecycleCallbackArgs& aArgs)
      61             :   {
      62             :     MOZ_ASSERT(mType == nsIDocument::eAttributeChanged,
      63             :                "Arguments are only used by attribute changed callback.");
      64             :     mArgs = aArgs;
      65             :   }
      66             : 
      67             :   void SetAdoptedCallbackArgs(LifecycleAdoptedCallbackArgs& aAdoptedCallbackArgs)
      68             :   {
      69             :     MOZ_ASSERT(mType == nsIDocument::eAdopted,
      70             :       "Arguments are only used by adopted callback.");
      71             :     mAdoptedCallbackArgs = aAdoptedCallbackArgs;
      72             :   }
      73             : 
      74             : private:
      75             :   // The this value to use for invocation of the callback.
      76             :   RefPtr<Element> mThisObject;
      77             :   RefPtr<CallbackFunction> mCallback;
      78             :   // The type of callback (eCreated, eAttached, etc.)
      79             :   nsIDocument::ElementCallbackType mType;
      80             :   // Arguments to be passed to the callback,
      81             :   // used by the attribute changed callback.
      82             :   LifecycleCallbackArgs mArgs;
      83             :   LifecycleAdoptedCallbackArgs mAdoptedCallbackArgs;
      84             : };
      85             : 
      86           0 : class CustomElementConstructor final : public CallbackFunction
      87             : {
      88             : public:
      89             :   explicit CustomElementConstructor(CallbackFunction* aOther)
      90             :     : CallbackFunction(aOther)
      91             :   {
      92             :     MOZ_ASSERT(JS::IsConstructor(mCallback));
      93             :   }
      94             : 
      95             :   already_AddRefed<Element> Construct(const char* aExecutionReason, ErrorResult& aRv);
      96             : };
      97             : 
      98             : // Each custom element has an associated callback queue and an element is
      99             : // being created flag.
     100             : struct CustomElementData
     101             : {
     102           0 :   NS_INLINE_DECL_REFCOUNTING(CustomElementData)
     103             : 
     104             :   // https://dom.spec.whatwg.org/#concept-element-custom-element-state
     105             :   // CustomElementData is only created on the element which is a custom element
     106             :   // or an upgrade candidate, so the state of an element without
     107             :   // CustomElementData is "uncustomized".
     108             :   enum class State {
     109             :     eUndefined,
     110             :     eFailed,
     111             :     eCustom
     112             :   };
     113             : 
     114             :   explicit CustomElementData(nsAtom* aType);
     115             :   CustomElementData(nsAtom* aType, State aState);
     116             : 
     117             :   // Custom element state as described in the custom element spec.
     118             :   State mState;
     119             :   // custom element reaction queue as described in the custom element spec.
     120             :   // There is 1 reaction in reaction queue, when 1) it becomes disconnected,
     121             :   // 2) it’s adopted into a new document, 3) its attributes are changed,
     122             :   // appended, removed, or replaced.
     123             :   // There are 3 reactions in reaction queue when doing upgrade operation,
     124             :   // e.g., create an element, insert a node.
     125             :   AutoTArray<UniquePtr<CustomElementReaction>, 3> mReactionQueue;
     126             : 
     127             :   void SetCustomElementDefinition(CustomElementDefinition* aDefinition);
     128             :   CustomElementDefinition* GetCustomElementDefinition();
     129             :   nsAtom* GetCustomElementType();
     130             : 
     131             :   void Traverse(nsCycleCollectionTraversalCallback& aCb) const;
     132             :   void Unlink();
     133             : 
     134             : private:
     135           0 :   virtual ~CustomElementData() {}
     136             : 
     137             :   // Custom element type, for <button is="x-button"> or <x-button>
     138             :   // this would be x-button.
     139             :   RefPtr<nsAtom> mType;
     140             :   RefPtr<CustomElementDefinition> mCustomElementDefinition;
     141             : };
     142             : 
     143             : #define ALREADY_CONSTRUCTED_MARKER nullptr
     144             : 
     145             : // The required information for a custom element as defined in:
     146             : // https://html.spec.whatwg.org/multipage/scripting.html#custom-element-definition
     147             : struct CustomElementDefinition
     148             : {
     149             :   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(CustomElementDefinition)
     150           0 :   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(CustomElementDefinition)
     151             : 
     152             :   CustomElementDefinition(nsAtom* aType,
     153             :                           nsAtom* aLocalName,
     154             :                           Function* aConstructor,
     155             :                           nsTArray<RefPtr<nsAtom>>&& aObservedAttributes,
     156             :                           UniquePtr<LifecycleCallbacks>&& aCallbacks);
     157             : 
     158             :   // The type (name) for this custom element, for <button is="x-foo"> or <x-foo>
     159             :   // this would be x-foo.
     160             :   RefPtr<nsAtom> mType;
     161             : 
     162             :   // The localname to (e.g. <button is=type> -- this would be button).
     163             :   RefPtr<nsAtom> mLocalName;
     164             : 
     165             :   // The custom element constructor.
     166             :   RefPtr<CustomElementConstructor> mConstructor;
     167             : 
     168             :   // The list of attributes that this custom element observes.
     169             :   nsTArray<RefPtr<nsAtom>> mObservedAttributes;
     170             : 
     171             :   // The lifecycle callbacks to call for this custom element.
     172             :   UniquePtr<LifecycleCallbacks> mCallbacks;
     173             : 
     174             :   // A construction stack. Use nullptr to represent an "already constructed marker".
     175             :   nsTArray<RefPtr<Element>> mConstructionStack;
     176             : 
     177             :   bool IsCustomBuiltIn()
     178             :   {
     179         156 :     return mType != mLocalName;
     180             :   }
     181             : 
     182           2 :   bool IsInObservedAttributeList(nsAtom* aName)
     183             :   {
     184           2 :     if (mObservedAttributes.IsEmpty()) {
     185             :       return false;
     186             :     }
     187             : 
     188           0 :     return mObservedAttributes.Contains(aName);
     189             :   }
     190             : 
     191             : private:
     192             :   ~CustomElementDefinition() {}
     193             : };
     194             : 
     195             : class CustomElementReaction
     196             : {
     197             : public:
     198             :   virtual ~CustomElementReaction() = default;
     199             :   virtual void Invoke(Element* aElement, ErrorResult& aRv) = 0;
     200             :   virtual void Traverse(nsCycleCollectionTraversalCallback& aCb) const = 0;
     201             : 
     202             :   bool IsUpgradeReaction()
     203             :   {
     204             :     return mIsUpgradeReaction;
     205             :   }
     206             : 
     207             : protected:
     208             :   bool mIsUpgradeReaction = false;
     209             : };
     210             : 
     211             : // https://html.spec.whatwg.org/multipage/scripting.html#custom-element-reactions-stack
     212             : class CustomElementReactionsStack
     213             : {
     214             : public:
     215           2 :   NS_INLINE_DECL_REFCOUNTING(CustomElementReactionsStack)
     216             : 
     217           2 :   CustomElementReactionsStack()
     218           2 :     : mIsBackupQueueProcessing(false)
     219             :     , mRecursionDepth(0)
     220           2 :     , mIsElementQueuePushedForCurrentRecursionDepth(false)
     221             :   {
     222           2 :   }
     223             : 
     224             :   // Hold a strong reference of Element so that it does not get cycle collected
     225             :   // before the reactions in its reaction queue are invoked.
     226             :   // The element reaction queues are stored in CustomElementData.
     227             :   // We need to lookup ElementReactionQueueMap again to get relevant reaction queue.
     228             :   // The choice of 3 for the auto size here is based on running Custom Elements
     229             :   // wpt tests.
     230             :   typedef AutoTArray<RefPtr<Element>, 3> ElementQueue;
     231             : 
     232             :   /**
     233             :    * Enqueue a custom element upgrade reaction
     234             :    * https://html.spec.whatwg.org/multipage/scripting.html#enqueue-a-custom-element-upgrade-reaction
     235             :    */
     236             :   void EnqueueUpgradeReaction(Element* aElement,
     237             :                               CustomElementDefinition* aDefinition);
     238             : 
     239             :   /**
     240             :    * Enqueue a custom element callback reaction
     241             :    * https://html.spec.whatwg.org/multipage/scripting.html#enqueue-a-custom-element-callback-reaction
     242             :    */
     243             :   void EnqueueCallbackReaction(Element* aElement,
     244             :                                UniquePtr<CustomElementCallback> aCustomElementCallback);
     245             : 
     246             :   /**
     247             :    * [CEReactions] Before executing the algorithm's steps.
     248             :    * Increase the current recursion depth, and the element queue is pushed
     249             :    * lazily when we really enqueue reactions.
     250             :    *
     251             :    * @return true if the element queue is pushed for "previous" recursion depth.
     252             :    */
     253             :   bool EnterCEReactions()
     254             :   {
     255           0 :     bool temp = mIsElementQueuePushedForCurrentRecursionDepth;
     256           0 :     mRecursionDepth++;
     257             :     // The is-element-queue-pushed flag is initially false when entering a new
     258             :     // recursion level. The original value will be cached in AutoCEReaction
     259             :     // and restored after leaving this recursion level.
     260           0 :     mIsElementQueuePushedForCurrentRecursionDepth = false;
     261             :     return temp;
     262             :   }
     263             : 
     264             :   /**
     265             :    * [CEReactions] After executing the algorithm's steps.
     266             :    * Pop and invoke the element queue if it is created and pushed for current
     267             :    * recursion depth, then decrease the current recursion depth.
     268             :    *
     269             :    * @param aCx JSContext used for handling exception thrown by algorithm's
     270             :    *            steps, this could be a nullptr.
     271             :    *        aWasElementQueuePushed used for restoring status after leaving
     272             :    *                               current recursion.
     273             :    */
     274           2 :   void LeaveCEReactions(JSContext* aCx, bool aWasElementQueuePushed)
     275             :   {
     276           2 :     MOZ_ASSERT(mRecursionDepth);
     277             : 
     278           2 :     if (mIsElementQueuePushedForCurrentRecursionDepth) {
     279           0 :       Maybe<JS::AutoSaveExceptionState> ases;
     280           0 :       if (aCx) {
     281           0 :         ases.emplace(aCx);
     282             :       }
     283           0 :       PopAndInvokeElementQueue();
     284             :     }
     285           2 :     mRecursionDepth--;
     286             :     // Restore the is-element-queue-pushed flag cached in AutoCEReaction when
     287             :     // leaving the recursion level.
     288           2 :     mIsElementQueuePushedForCurrentRecursionDepth = aWasElementQueuePushed;
     289             : 
     290           2 :     MOZ_ASSERT_IF(!mRecursionDepth, mReactionsStack.IsEmpty());
     291           2 :   }
     292             : 
     293             : private:
     294           0 :   ~CustomElementReactionsStack() {};
     295             : 
     296             :   /**
     297             :    * Push a new element queue onto the custom element reactions stack.
     298             :    */
     299             :   void CreateAndPushElementQueue();
     300             : 
     301             :   /**
     302             :    * Pop the element queue from the custom element reactions stack, and invoke
     303             :    * custom element reactions in that queue.
     304             :    */
     305             :   void PopAndInvokeElementQueue();
     306             : 
     307             :   // The choice of 8 for the auto size here is based on gut feeling.
     308             :   AutoTArray<UniquePtr<ElementQueue>, 8> mReactionsStack;
     309             :   ElementQueue mBackupQueue;
     310             :   // https://html.spec.whatwg.org/#enqueue-an-element-on-the-appropriate-element-queue
     311             :   bool mIsBackupQueueProcessing;
     312             : 
     313             :   void InvokeBackupQueue();
     314             : 
     315             :   /**
     316             :    * Invoke custom element reactions
     317             :    * https://html.spec.whatwg.org/multipage/scripting.html#invoke-custom-element-reactions
     318             :    */
     319             :   void InvokeReactions(ElementQueue* aElementQueue, nsIGlobalObject* aGlobal);
     320             : 
     321             :   void Enqueue(Element* aElement, CustomElementReaction* aReaction);
     322             : 
     323             :   // Current [CEReactions] recursion depth.
     324             :   uint32_t mRecursionDepth;
     325             :   // True if the element queue is pushed into reaction stack for current
     326             :   // recursion depth. This will be cached in AutoCEReaction when entering a new
     327             :   // CEReaction recursion and restored after leaving the recursion.
     328             :   bool mIsElementQueuePushedForCurrentRecursionDepth;
     329             : 
     330             : private:
     331           0 :   class BackupQueueMicroTask final : public mozilla::MicroTaskRunnable {
     332             :     public:
     333             :       explicit BackupQueueMicroTask(
     334             :         CustomElementReactionsStack* aReactionStack)
     335             :         : MicroTaskRunnable()
     336             :         , mReactionStack(aReactionStack)
     337             :       {
     338             :         MOZ_ASSERT(!mReactionStack->mIsBackupQueueProcessing,
     339             :                    "mIsBackupQueueProcessing should be initially false");
     340             :         mReactionStack->mIsBackupQueueProcessing = true;
     341             :       }
     342             : 
     343           0 :       virtual void Run(AutoSlowOperation& aAso) override
     344             :       {
     345           0 :         mReactionStack->InvokeBackupQueue();
     346           0 :         mReactionStack->mIsBackupQueueProcessing = false;
     347           0 :       }
     348             : 
     349             :     private:
     350             :       RefPtr<CustomElementReactionsStack> mReactionStack;
     351             :   };
     352             : };
     353             : 
     354             : class CustomElementRegistry final : public nsISupports,
     355             :                                     public nsWrapperCache
     356             : {
     357             :   // Allow nsDocument to access mCustomDefinitions and mCandidatesMap.
     358             :   friend class ::nsDocument;
     359             : 
     360             : public:
     361             :   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     362             :   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CustomElementRegistry)
     363             : 
     364             : public:
     365             :   static bool IsCustomElementEnabled(JSContext* aCx, JSObject* aObject);
     366             :   static bool IsCustomElementEnabled(nsIDocument* aDoc);
     367             : 
     368             :   explicit CustomElementRegistry(nsPIDOMWindowInner* aWindow);
     369             : 
     370             : private:
     371             :   class RunCustomElementCreationCallback : public mozilla::Runnable
     372             :   {
     373             :   public:
     374             :     NS_DECL_NSIRUNNABLE
     375             :     explicit RunCustomElementCreationCallback(CustomElementRegistry* aRegistry,
     376             :                                               nsAtom* aAtom,
     377             :                                               CustomElementCreationCallback* aCallback)
     378             :       : mozilla::Runnable("CustomElementRegistry::RunCustomElementCreationCallback")
     379             :       , mRegistry(aRegistry)
     380             :       , mAtom(aAtom)
     381             :       , mCallback(aCallback)
     382             :     {
     383             :     }
     384             :     private:
     385             :       RefPtr<CustomElementRegistry> mRegistry;
     386             :       RefPtr<nsAtom> mAtom;
     387             :       RefPtr<CustomElementCreationCallback> mCallback;
     388             :   };
     389             : 
     390             : public:
     391             :   /**
     392             :    * Looking up a custom element definition.
     393             :    * https://html.spec.whatwg.org/#look-up-a-custom-element-definition
     394             :    */
     395             :   CustomElementDefinition* LookupCustomElementDefinition(
     396             :     nsAtom* aNameAtom, nsAtom* aTypeAtom);
     397             : 
     398             :   CustomElementDefinition* LookupCustomElementDefinition(
     399             :     JSContext* aCx, JSObject *aConstructor) const;
     400             : 
     401             :   static void EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
     402             :                                        Element* aCustomElement,
     403             :                                        LifecycleCallbackArgs* aArgs,
     404             :                                        LifecycleAdoptedCallbackArgs* aAdoptedCallbackArgs,
     405             :                                        CustomElementDefinition* aDefinition);
     406             : 
     407             :   /**
     408             :    * Upgrade an element.
     409             :    * https://html.spec.whatwg.org/multipage/scripting.html#upgrades
     410             :    */
     411             :   static void Upgrade(Element* aElement, CustomElementDefinition* aDefinition, ErrorResult& aRv);
     412             : 
     413             :   /**
     414             :    * Registers an unresolved custom element that is a candidate for
     415             :    * upgrade. |aTypeName| is the name of the custom element type, if it is not
     416             :    * provided, then element name is used. |aTypeName| should be provided
     417             :    * when registering a custom element that extends an existing
     418             :    * element. e.g. <button is="x-button">.
     419             :    */
     420             :   void RegisterUnresolvedElement(Element* aElement,
     421             :                                  nsAtom* aTypeName = nullptr);
     422             : 
     423             :   /**
     424             :    * Unregister an unresolved custom element that is a candidate for
     425             :    * upgrade when a custom element is removed from tree.
     426             :    */
     427             :   void UnregisterUnresolvedElement(Element* aElement,
     428             :                                    nsAtom* aTypeName = nullptr);
     429             : 
     430             :   /**
     431             :    * Register an element to be upgraded when the custom element creation
     432             :    * callback is executed.
     433             :    *
     434             :    * To be used when LookupCustomElementDefinition() didn't return a definition,
     435             :    * but with the callback scheduled to be run.
     436             :    */
     437        2680 :   inline void RegisterCallbackUpgradeElement(Element* aElement,
     438             :                                              nsAtom* aTypeName = nullptr)
     439             :   {
     440        5360 :     if (mElementCreationCallbacksUpgradeCandidatesMap.IsEmpty()) {
     441        2680 :       return;
     442             :     }
     443             : 
     444           0 :     RefPtr<nsAtom> typeName = aTypeName;
     445           0 :     if (!typeName) {
     446           0 :       typeName = aElement->NodeInfo()->NameAtom();
     447             :     }
     448             : 
     449             :     nsTHashtable<nsRefPtrHashKey<nsIWeakReference>>* elements =
     450           0 :       mElementCreationCallbacksUpgradeCandidatesMap.Get(typeName);
     451             : 
     452             :     // If there isn't a table, there won't be a definition added by the callback.
     453           0 :     if (!elements) {
     454           0 :       return;
     455             :     }
     456             : 
     457           0 :     nsWeakPtr elem = do_GetWeakReference(aElement);
     458           0 :     elements->PutEntry(elem);
     459             :   }
     460             : 
     461             : private:
     462             :   ~CustomElementRegistry();
     463             : 
     464             :   static UniquePtr<CustomElementCallback> CreateCustomElementCallback(
     465             :     nsIDocument::ElementCallbackType aType, Element* aCustomElement,
     466             :     LifecycleCallbackArgs* aArgs,
     467             :     LifecycleAdoptedCallbackArgs* aAdoptedCallbackArgs,
     468             :     CustomElementDefinition* aDefinition);
     469             : 
     470             :   void UpgradeCandidates(nsAtom* aKey,
     471             :                          CustomElementDefinition* aDefinition,
     472             :                          ErrorResult& aRv);
     473             : 
     474             :   typedef nsRefPtrHashtable<nsRefPtrHashKey<nsAtom>, CustomElementDefinition>
     475             :     DefinitionMap;
     476             :   typedef nsRefPtrHashtable<nsRefPtrHashKey<nsAtom>, CustomElementCreationCallback>
     477             :     ElementCreationCallbackMap;
     478             :   typedef nsClassHashtable<nsRefPtrHashKey<nsAtom>,
     479             :                            nsTHashtable<nsRefPtrHashKey<nsIWeakReference>>>
     480             :     CandidateMap;
     481             :   typedef JS::GCHashMap<JS::Heap<JSObject*>,
     482             :                         RefPtr<nsAtom>,
     483             :                         js::MovableCellHasher<JS::Heap<JSObject*>>,
     484             :                         js::SystemAllocPolicy> ConstructorMap;
     485             : 
     486             :   // Hashtable for custom element definitions in web components.
     487             :   // Custom prototypes are stored in the compartment where definition was
     488             :   // defined.
     489             :   DefinitionMap mCustomDefinitions;
     490             : 
     491             :   // Hashtable for chrome-only callbacks that is called *before* we return
     492             :   // a CustomElementDefinition, when the typeAtom matches.
     493             :   // The callbacks are registered with the setElementCreationCallback method.
     494             :   ElementCreationCallbackMap mElementCreationCallbacks;
     495             : 
     496             :   // Hashtable for looking up definitions by using constructor as key.
     497             :   // Custom elements' name are stored here and we need to lookup
     498             :   // mCustomDefinitions again to get definitions.
     499             :   ConstructorMap mConstructors;
     500             : 
     501             :   typedef nsRefPtrHashtable<nsRefPtrHashKey<nsAtom>, Promise>
     502             :     WhenDefinedPromiseMap;
     503             :   WhenDefinedPromiseMap mWhenDefinedPromiseMap;
     504             : 
     505             :   // The "upgrade candidates map" from the web components spec. Maps from a
     506             :   // namespace id and local name to a list of elements to upgrade if that
     507             :   // element is registered as a custom element.
     508             :   CandidateMap mCandidatesMap;
     509             : 
     510             :   // If an element creation callback is found, the nsTHashtable for the
     511             :   // type is created here, and elements will later be upgraded.
     512             :   CandidateMap mElementCreationCallbacksUpgradeCandidatesMap;
     513             : 
     514             :   nsCOMPtr<nsPIDOMWindowInner> mWindow;
     515             : 
     516             :   // It is used to prevent reentrant invocations of element definition.
     517             :   bool mIsCustomDefinitionRunning;
     518             : 
     519             : private:
     520             :   class MOZ_RAII AutoSetRunningFlag final {
     521             :     public:
     522             :       explicit AutoSetRunningFlag(CustomElementRegistry* aRegistry)
     523             :         : mRegistry(aRegistry)
     524             :       {
     525             :         MOZ_ASSERT(!mRegistry->mIsCustomDefinitionRunning,
     526             :                    "IsCustomDefinitionRunning flag should be initially false");
     527             :         mRegistry->mIsCustomDefinitionRunning = true;
     528             :       }
     529             : 
     530             :       ~AutoSetRunningFlag() {
     531             :         mRegistry->mIsCustomDefinitionRunning = false;
     532             :       }
     533             : 
     534             :     private:
     535             :       CustomElementRegistry* mRegistry;
     536             :   };
     537             : 
     538             : public:
     539             :   nsISupports* GetParentObject() const;
     540             : 
     541             :   DocGroup* GetDocGroup() const;
     542             : 
     543             :   virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
     544             : 
     545             :   void Define(JSContext* aCx, const nsAString& aName,
     546             :               Function& aFunctionConstructor,
     547             :               const ElementDefinitionOptions& aOptions, ErrorResult& aRv);
     548             : 
     549             :   void Get(JSContext* cx, const nsAString& name,
     550             :            JS::MutableHandle<JS::Value> aRetVal);
     551             : 
     552             :   already_AddRefed<Promise> WhenDefined(const nsAString& aName, ErrorResult& aRv);
     553             : 
     554             :   // Chrome-only method that give JS an opportunity to only load the custom
     555             :   // element definition script when needed.
     556             :   void SetElementCreationCallback(const nsAString& aName, CustomElementCreationCallback& aCallback, ErrorResult& aRv);
     557             : };
     558             : 
     559             : class MOZ_RAII AutoCEReaction final {
     560             :   public:
     561             :     // JSContext is allowed to be a nullptr if we are guaranteeing that we're
     562             :     // not doing something that might throw but not finish reporting a JS
     563             :     // exception during the lifetime of the AutoCEReaction.
     564           0 :     AutoCEReaction(CustomElementReactionsStack* aReactionsStack, JSContext* aCx)
     565           0 :       : mReactionsStack(aReactionsStack)
     566           0 :       , mCx(aCx)
     567             :     {
     568           0 :       mIsElementQueuePushedForPreviousRecursionDepth =
     569           0 :         mReactionsStack->EnterCEReactions();
     570           0 :     }
     571             : 
     572           2 :     ~AutoCEReaction()
     573           2 :     {
     574           2 :       mReactionsStack->LeaveCEReactions(
     575           2 :         mCx, mIsElementQueuePushedForPreviousRecursionDepth);
     576             :     }
     577             : 
     578             :   private:
     579             :     RefPtr<CustomElementReactionsStack> mReactionsStack;
     580             :     JSContext* mCx;
     581             :     bool mIsElementQueuePushedForPreviousRecursionDepth;
     582             : };
     583             : 
     584             : } // namespace dom
     585             : } // namespace mozilla
     586             : 
     587             : 
     588             : #endif // mozilla_dom_CustomElementRegistry_h

Generated by: LCOV version 1.13-14-ga5dd952