2018-01-19 03:59:58 +08:00
|
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
|
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
|
|
|
|
|
/* 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
|
|
|
|
|
|
|
2020-01-02 21:24:22 -05:00
|
|
|
|
#include "js/GCHashTable.h"
|
2018-01-19 03:59:58 +08:00
|
|
|
|
#include "js/TypeDecls.h"
|
|
|
|
|
|
#include "mozilla/Attributes.h"
|
|
|
|
|
|
#include "mozilla/ErrorResult.h"
|
|
|
|
|
|
#include "mozilla/dom/BindingDeclarations.h"
|
2020-01-02 21:24:22 -05:00
|
|
|
|
#include "mozilla/dom/FunctionBinding.h"
|
2020-01-05 15:31:44 -05:00
|
|
|
|
#include "mozilla/dom/WebComponentsBinding.h"
|
2018-01-19 03:59:58 +08:00
|
|
|
|
#include "nsCycleCollectionParticipant.h"
|
2020-01-05 15:31:44 -05:00
|
|
|
|
#include "nsGenericHTMLElement.h"
|
2018-01-19 03:59:58 +08:00
|
|
|
|
#include "nsWrapperCache.h"
|
|
|
|
|
|
|
|
|
|
|
|
class nsDocument;
|
|
|
|
|
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
|
|
namespace dom {
|
|
|
|
|
|
|
|
|
|
|
|
struct CustomElementData;
|
|
|
|
|
|
struct ElementDefinitionOptions;
|
|
|
|
|
|
class CallbackFunction;
|
2020-01-04 19:47:42 -05:00
|
|
|
|
class CustomElementReaction;
|
2018-01-19 03:59:58 +08:00
|
|
|
|
class Function;
|
|
|
|
|
|
class Promise;
|
|
|
|
|
|
|
|
|
|
|
|
struct LifecycleCallbackArgs
|
|
|
|
|
|
{
|
|
|
|
|
|
nsString name;
|
|
|
|
|
|
nsString oldValue;
|
|
|
|
|
|
nsString newValue;
|
2020-01-05 11:25:37 -05:00
|
|
|
|
nsString namespaceURI;
|
2018-01-19 03:59:58 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class CustomElementCallback
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
CustomElementCallback(Element* aThisObject,
|
|
|
|
|
|
nsIDocument::ElementCallbackType aCallbackType,
|
|
|
|
|
|
CallbackFunction* aCallback,
|
|
|
|
|
|
CustomElementData* aOwnerData);
|
|
|
|
|
|
void Traverse(nsCycleCollectionTraversalCallback& aCb) const;
|
|
|
|
|
|
void Call();
|
|
|
|
|
|
void SetArgs(LifecycleCallbackArgs& aArgs)
|
|
|
|
|
|
{
|
|
|
|
|
|
MOZ_ASSERT(mType == nsIDocument::eAttributeChanged,
|
|
|
|
|
|
"Arguments are only used by attribute changed callback.");
|
|
|
|
|
|
mArgs = aArgs;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
// The this value to use for invocation of the callback.
|
|
|
|
|
|
RefPtr<Element> mThisObject;
|
|
|
|
|
|
RefPtr<CallbackFunction> mCallback;
|
|
|
|
|
|
// The type of callback (eCreated, eAttached, etc.)
|
|
|
|
|
|
nsIDocument::ElementCallbackType mType;
|
|
|
|
|
|
// Arguments to be passed to the callback,
|
|
|
|
|
|
// used by the attribute changed callback.
|
|
|
|
|
|
LifecycleCallbackArgs mArgs;
|
|
|
|
|
|
// CustomElementData that contains this callback in the
|
|
|
|
|
|
// callback queue.
|
|
|
|
|
|
CustomElementData* mOwnerData;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2020-01-05 11:21:03 -05:00
|
|
|
|
class CustomElementConstructor final : public CallbackFunction
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
explicit CustomElementConstructor(CallbackFunction* aOther)
|
|
|
|
|
|
: CallbackFunction(aOther)
|
|
|
|
|
|
{
|
|
|
|
|
|
MOZ_ASSERT(JS::IsConstructor(mCallback));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
already_AddRefed<Element> Construct(const char* aExecutionReason, ErrorResult& aRv);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2018-01-19 03:59:58 +08:00
|
|
|
|
// Each custom element has an associated callback queue and an element is
|
|
|
|
|
|
// being created flag.
|
|
|
|
|
|
struct CustomElementData
|
|
|
|
|
|
{
|
|
|
|
|
|
NS_INLINE_DECL_REFCOUNTING(CustomElementData)
|
|
|
|
|
|
|
2020-01-04 13:24:58 -05:00
|
|
|
|
// 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
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2018-01-19 03:59:58 +08:00
|
|
|
|
explicit CustomElementData(nsIAtom* aType);
|
2020-01-04 13:24:58 -05:00
|
|
|
|
CustomElementData(nsIAtom* aType, State aState);
|
2018-01-19 03:59:58 +08:00
|
|
|
|
// Custom element type, for <button is="x-button"> or <x-button>
|
|
|
|
|
|
// this would be x-button.
|
|
|
|
|
|
nsCOMPtr<nsIAtom> mType;
|
|
|
|
|
|
// Element is being created flag as described in the custom elements spec.
|
|
|
|
|
|
bool mElementIsBeingCreated;
|
|
|
|
|
|
// Flag to determine if the created callback has been invoked, thus it
|
|
|
|
|
|
// determines if other callbacks can be enqueued.
|
|
|
|
|
|
bool mCreatedCallbackInvoked;
|
2020-01-04 13:24:58 -05:00
|
|
|
|
// Custom element state as described in the custom element spec.
|
|
|
|
|
|
State mState;
|
2020-01-04 19:47:42 -05:00
|
|
|
|
// 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.
|
2020-01-04 23:29:10 -05:00
|
|
|
|
AutoTArray<UniquePtr<CustomElementReaction>, 3> mReactionQueue;
|
2018-01-19 03:59:58 +08:00
|
|
|
|
|
2020-01-05 15:31:44 -05:00
|
|
|
|
RefPtr<CustomElementDefinition> mCustomElementDefinition;
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
SetCustomElementDefinition(CustomElementDefinition* aDefinition)
|
|
|
|
|
|
{
|
|
|
|
|
|
MOZ_ASSERT(!mCustomElementDefinition);
|
|
|
|
|
|
|
|
|
|
|
|
mCustomElementDefinition = aDefinition;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CustomElementDefinition*
|
|
|
|
|
|
GetCustomElementDefinition()
|
|
|
|
|
|
{
|
|
|
|
|
|
return mCustomElementDefinition;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-01-19 03:59:58 +08:00
|
|
|
|
private:
|
|
|
|
|
|
virtual ~CustomElementData() {}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2020-01-05 10:26:29 -05:00
|
|
|
|
#define ALEADY_CONSTRUCTED_MARKER nullptr
|
|
|
|
|
|
|
2018-01-19 03:59:58 +08:00
|
|
|
|
// The required information for a custom element as defined in:
|
|
|
|
|
|
// https://html.spec.whatwg.org/multipage/scripting.html#custom-element-definition
|
|
|
|
|
|
struct CustomElementDefinition
|
|
|
|
|
|
{
|
2020-01-05 15:31:44 -05:00
|
|
|
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(CustomElementDefinition)
|
|
|
|
|
|
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(CustomElementDefinition)
|
|
|
|
|
|
|
2018-01-19 03:59:58 +08:00
|
|
|
|
CustomElementDefinition(nsIAtom* aType,
|
|
|
|
|
|
nsIAtom* aLocalName,
|
2020-01-05 11:21:03 -05:00
|
|
|
|
Function* aConstructor,
|
2020-01-05 12:13:14 -05:00
|
|
|
|
nsCOMArray<nsIAtom>&& aObservedAttributes,
|
2018-01-19 03:59:58 +08:00
|
|
|
|
JSObject* aPrototype,
|
|
|
|
|
|
mozilla::dom::LifecycleCallbacks* aCallbacks,
|
|
|
|
|
|
uint32_t aDocOrder);
|
|
|
|
|
|
|
|
|
|
|
|
// The type (name) for this custom element.
|
|
|
|
|
|
nsCOMPtr<nsIAtom> mType;
|
|
|
|
|
|
|
|
|
|
|
|
// The localname to (e.g. <button is=type> -- this would be button).
|
|
|
|
|
|
nsCOMPtr<nsIAtom> mLocalName;
|
|
|
|
|
|
|
|
|
|
|
|
// The custom element constructor.
|
2020-01-05 11:21:03 -05:00
|
|
|
|
RefPtr<CustomElementConstructor> mConstructor;
|
2018-01-19 03:59:58 +08:00
|
|
|
|
|
2020-01-05 12:13:14 -05:00
|
|
|
|
// The list of attributes that this custom element observes.
|
|
|
|
|
|
nsCOMArray<nsIAtom> mObservedAttributes;
|
|
|
|
|
|
|
2018-01-19 03:59:58 +08:00
|
|
|
|
// The prototype to use for new custom elements of this type.
|
|
|
|
|
|
JS::Heap<JSObject *> mPrototype;
|
|
|
|
|
|
|
|
|
|
|
|
// The lifecycle callbacks to call for this custom element.
|
2020-01-04 23:29:10 -05:00
|
|
|
|
UniquePtr<mozilla::dom::LifecycleCallbacks> mCallbacks;
|
2018-01-19 03:59:58 +08:00
|
|
|
|
|
2020-01-05 10:26:29 -05:00
|
|
|
|
// A construction stack. Use nullptr to represent an "already constructed marker".
|
|
|
|
|
|
nsTArray<RefPtr<nsGenericHTMLElement>> mConstructionStack;
|
2018-01-19 03:59:58 +08:00
|
|
|
|
|
|
|
|
|
|
// The document custom element order.
|
|
|
|
|
|
uint32_t mDocOrder;
|
2020-01-02 21:25:47 -05:00
|
|
|
|
|
2020-01-05 12:13:14 -05:00
|
|
|
|
bool IsCustomBuiltIn()
|
|
|
|
|
|
{
|
2020-01-02 21:25:47 -05:00
|
|
|
|
return mType != mLocalName;
|
|
|
|
|
|
}
|
2020-01-05 12:13:14 -05:00
|
|
|
|
|
|
|
|
|
|
bool IsInObservedAttributeList(nsIAtom* aName)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (mObservedAttributes.IsEmpty()) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return mObservedAttributes.Contains(aName);
|
|
|
|
|
|
}
|
2020-01-05 15:31:44 -05:00
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
~CustomElementDefinition() {}
|
2018-01-19 03:59:58 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2020-01-02 22:04:11 -05:00
|
|
|
|
class CustomElementReaction
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
explicit CustomElementReaction(CustomElementRegistry* aRegistry,
|
|
|
|
|
|
CustomElementDefinition* aDefinition)
|
|
|
|
|
|
: mRegistry(aRegistry)
|
|
|
|
|
|
, mDefinition(aDefinition)
|
|
|
|
|
|
{
|
2020-01-04 23:29:10 -05:00
|
|
|
|
}
|
2020-01-02 22:04:11 -05:00
|
|
|
|
|
|
|
|
|
|
virtual ~CustomElementReaction() = default;
|
2020-01-05 11:21:03 -05:00
|
|
|
|
virtual void Invoke(Element* aElement, ErrorResult& aRv) = 0;
|
2020-01-04 23:29:10 -05:00
|
|
|
|
virtual void Traverse(nsCycleCollectionTraversalCallback& aCb) const
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
2020-01-02 22:04:11 -05:00
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
CustomElementRegistry* mRegistry;
|
|
|
|
|
|
CustomElementDefinition* mDefinition;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class CustomElementUpgradeReaction final : public CustomElementReaction
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
explicit CustomElementUpgradeReaction(CustomElementRegistry* aRegistry,
|
|
|
|
|
|
CustomElementDefinition* aDefinition)
|
|
|
|
|
|
: CustomElementReaction(aRegistry, aDefinition)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
2020-01-05 11:21:03 -05:00
|
|
|
|
virtual void Invoke(Element* aElement, ErrorResult& aRv) override;
|
2020-01-02 22:04:11 -05:00
|
|
|
|
};
|
|
|
|
|
|
|
2020-01-04 23:29:10 -05:00
|
|
|
|
class CustomElementCallbackReaction final : public CustomElementReaction
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
CustomElementCallbackReaction(CustomElementRegistry* aRegistry,
|
|
|
|
|
|
CustomElementDefinition* aDefinition,
|
|
|
|
|
|
UniquePtr<CustomElementCallback> aCustomElementCallback)
|
|
|
|
|
|
: CustomElementReaction(aRegistry, aDefinition)
|
|
|
|
|
|
, mCustomElementCallback(Move(aCustomElementCallback))
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
virtual void Traverse(nsCycleCollectionTraversalCallback& aCb) const override
|
|
|
|
|
|
{
|
|
|
|
|
|
mCustomElementCallback->Traverse(aCb);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
2020-01-05 11:21:03 -05:00
|
|
|
|
virtual void Invoke(Element* aElement, ErrorResult& aRv) override;
|
2020-01-04 23:29:10 -05:00
|
|
|
|
UniquePtr<CustomElementCallback> mCustomElementCallback;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2020-01-03 22:18:55 -05:00
|
|
|
|
// https://html.spec.whatwg.org/multipage/scripting.html#custom-element-reactions-stack
|
|
|
|
|
|
class CustomElementReactionsStack
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
NS_INLINE_DECL_REFCOUNTING(CustomElementReactionsStack)
|
|
|
|
|
|
|
|
|
|
|
|
CustomElementReactionsStack()
|
|
|
|
|
|
: mIsBackupQueueProcessing(false)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// nsWeakPtr is a weak pointer of Element
|
2020-01-04 19:47:42 -05:00
|
|
|
|
// The element reaction queues are stored in CustomElementData.
|
2020-01-03 22:18:55 -05:00
|
|
|
|
// We need to lookup ElementReactionQueueMap again to get relevant reaction queue.
|
2020-01-04 10:34:36 -05:00
|
|
|
|
// The choice of 1 for the auto size here is based on gut feeling.
|
|
|
|
|
|
typedef AutoTArray<nsWeakPtr, 1> ElementQueue;
|
2020-01-03 22:18:55 -05:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Enqueue a custom element upgrade reaction
|
|
|
|
|
|
* https://html.spec.whatwg.org/multipage/scripting.html#enqueue-a-custom-element-upgrade-reaction
|
|
|
|
|
|
*/
|
|
|
|
|
|
void EnqueueUpgradeReaction(CustomElementRegistry* aRegistry,
|
|
|
|
|
|
Element* aElement,
|
|
|
|
|
|
CustomElementDefinition* aDefinition);
|
|
|
|
|
|
|
2020-01-04 23:29:10 -05:00
|
|
|
|
/**
|
|
|
|
|
|
* Enqueue a custom element callback reaction
|
|
|
|
|
|
* https://html.spec.whatwg.org/multipage/scripting.html#enqueue-a-custom-element-callback-reaction
|
|
|
|
|
|
*/
|
|
|
|
|
|
void EnqueueCallbackReaction(CustomElementRegistry* aRegistry,
|
|
|
|
|
|
Element* aElement,
|
|
|
|
|
|
CustomElementDefinition* aDefinition,
|
|
|
|
|
|
UniquePtr<CustomElementCallback> aCustomElementCallback);
|
|
|
|
|
|
|
2020-01-03 22:18:55 -05:00
|
|
|
|
// [CEReactions] Before executing the algorithm's steps
|
|
|
|
|
|
// Push a new element queue onto the custom element reactions stack.
|
|
|
|
|
|
void CreateAndPushElementQueue();
|
|
|
|
|
|
|
|
|
|
|
|
// [CEReactions] After executing the algorithm's steps
|
|
|
|
|
|
// Pop the element queue from the custom element reactions stack,
|
|
|
|
|
|
// and invoke custom element reactions in that queue.
|
|
|
|
|
|
void PopAndInvokeElementQueue();
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
~CustomElementReactionsStack() {};
|
|
|
|
|
|
|
2020-01-04 10:34:36 -05:00
|
|
|
|
// The choice of 8 for the auto size here is based on gut feeling.
|
2020-01-05 10:31:42 -05:00
|
|
|
|
AutoTArray<UniquePtr<ElementQueue>, 8> mReactionsStack;
|
2020-01-03 22:18:55 -05:00
|
|
|
|
ElementQueue mBackupQueue;
|
|
|
|
|
|
// https://html.spec.whatwg.org/#enqueue-an-element-on-the-appropriate-element-queue
|
|
|
|
|
|
bool mIsBackupQueueProcessing;
|
|
|
|
|
|
|
|
|
|
|
|
void InvokeBackupQueue();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Invoke custom element reactions
|
|
|
|
|
|
* https://html.spec.whatwg.org/multipage/scripting.html#invoke-custom-element-reactions
|
|
|
|
|
|
*/
|
2020-01-05 11:21:03 -05:00
|
|
|
|
void InvokeReactions(ElementQueue* aElementQueue, nsIGlobalObject* aGlobal);
|
2020-01-03 22:18:55 -05:00
|
|
|
|
|
|
|
|
|
|
void Enqueue(Element* aElement, CustomElementReaction* aReaction);
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
class ProcessBackupQueueRunnable : public mozilla::Runnable {
|
|
|
|
|
|
public:
|
|
|
|
|
|
explicit ProcessBackupQueueRunnable(CustomElementReactionsStack* aReactionStack)
|
|
|
|
|
|
: mReactionStack(aReactionStack)
|
|
|
|
|
|
{
|
|
|
|
|
|
MOZ_ASSERT(!mReactionStack->mIsBackupQueueProcessing,
|
|
|
|
|
|
"mIsBackupQueueProcessing should be initially false");
|
|
|
|
|
|
mReactionStack->mIsBackupQueueProcessing = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHOD Run() override
|
|
|
|
|
|
{
|
|
|
|
|
|
mReactionStack->InvokeBackupQueue();
|
|
|
|
|
|
mReactionStack->mIsBackupQueueProcessing = false;
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
RefPtr<CustomElementReactionsStack> mReactionStack;
|
|
|
|
|
|
};
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2018-01-19 03:59:58 +08:00
|
|
|
|
class CustomElementRegistry final : public nsISupports,
|
|
|
|
|
|
public nsWrapperCache
|
|
|
|
|
|
{
|
|
|
|
|
|
// Allow nsDocument to access mCustomDefinitions and mCandidatesMap.
|
|
|
|
|
|
friend class ::nsDocument;
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
|
|
|
|
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CustomElementRegistry)
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
static bool IsCustomElementEnabled(JSContext* aCx = nullptr,
|
|
|
|
|
|
JSObject* aObject = nullptr);
|
2020-01-03 18:50:56 -05:00
|
|
|
|
|
|
|
|
|
|
explicit CustomElementRegistry(nsPIDOMWindowInner* aWindow);
|
|
|
|
|
|
|
2018-01-19 03:59:58 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* Looking up a custom element definition.
|
|
|
|
|
|
* https://html.spec.whatwg.org/#look-up-a-custom-element-definition
|
|
|
|
|
|
*/
|
|
|
|
|
|
CustomElementDefinition* LookupCustomElementDefinition(
|
|
|
|
|
|
const nsAString& aLocalName, const nsAString* aIs = nullptr) const;
|
|
|
|
|
|
|
2020-01-02 21:25:47 -05:00
|
|
|
|
CustomElementDefinition* LookupCustomElementDefinition(
|
|
|
|
|
|
JSContext* aCx, JSObject *aConstructor) const;
|
|
|
|
|
|
|
2018-01-19 03:59:58 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* Enqueue created callback or register upgrade candidate for
|
|
|
|
|
|
* newly created custom elements, possibly extending an existing type.
|
|
|
|
|
|
* ex. <x-button>, <button is="x-button> (type extension)
|
|
|
|
|
|
*/
|
|
|
|
|
|
void SetupCustomElement(Element* aElement, const nsAString* aTypeExtension);
|
|
|
|
|
|
|
|
|
|
|
|
void EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
|
|
|
|
|
|
Element* aCustomElement,
|
|
|
|
|
|
LifecycleCallbackArgs* aArgs,
|
|
|
|
|
|
CustomElementDefinition* aDefinition);
|
|
|
|
|
|
|
|
|
|
|
|
void GetCustomPrototype(nsIAtom* aAtom,
|
|
|
|
|
|
JS::MutableHandle<JSObject*> aPrototype);
|
|
|
|
|
|
|
2020-01-05 11:21:03 -05:00
|
|
|
|
/**
|
|
|
|
|
|
* Upgrade an element.
|
|
|
|
|
|
* https://html.spec.whatwg.org/multipage/scripting.html#upgrades
|
|
|
|
|
|
*/
|
2020-01-05 12:51:10 -05:00
|
|
|
|
static void Upgrade(Element* aElement, CustomElementDefinition* aDefinition, ErrorResult& aRv);
|
2020-01-02 22:04:11 -05:00
|
|
|
|
|
2018-01-19 03:59:58 +08:00
|
|
|
|
private:
|
|
|
|
|
|
~CustomElementRegistry();
|
|
|
|
|
|
|
2020-01-04 23:29:10 -05:00
|
|
|
|
UniquePtr<CustomElementCallback> CreateCustomElementCallback(
|
|
|
|
|
|
nsIDocument::ElementCallbackType aType, Element* aCustomElement,
|
|
|
|
|
|
LifecycleCallbackArgs* aArgs, CustomElementDefinition* aDefinition);
|
|
|
|
|
|
|
2018-01-19 03:59:58 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* Registers an unresolved custom element that is a candidate for
|
|
|
|
|
|
* upgrade when the definition is registered via registerElement.
|
|
|
|
|
|
* |aTypeName| is the name of the custom element type, if it is not
|
|
|
|
|
|
* provided, then element name is used. |aTypeName| should be provided
|
|
|
|
|
|
* when registering a custom element that extends an existing
|
|
|
|
|
|
* element. e.g. <button is="x-button">.
|
|
|
|
|
|
*/
|
|
|
|
|
|
void RegisterUnresolvedElement(Element* aElement,
|
|
|
|
|
|
nsIAtom* aTypeName = nullptr);
|
|
|
|
|
|
|
2020-01-05 10:30:04 -05:00
|
|
|
|
void UpgradeCandidates(nsIAtom* aKey,
|
2020-01-03 22:18:55 -05:00
|
|
|
|
CustomElementDefinition* aDefinition,
|
|
|
|
|
|
ErrorResult& aRv);
|
2020-01-02 22:04:11 -05:00
|
|
|
|
|
2020-01-05 15:31:44 -05:00
|
|
|
|
typedef nsRefPtrHashtable<nsISupportsHashKey, CustomElementDefinition>
|
2018-01-19 03:59:58 +08:00
|
|
|
|
DefinitionMap;
|
|
|
|
|
|
typedef nsClassHashtable<nsISupportsHashKey, nsTArray<nsWeakPtr>>
|
|
|
|
|
|
CandidateMap;
|
2020-01-02 21:24:22 -05:00
|
|
|
|
typedef JS::GCHashMap<JS::Heap<JSObject*>,
|
|
|
|
|
|
nsCOMPtr<nsIAtom>,
|
|
|
|
|
|
js::MovableCellHasher<JS::Heap<JSObject*>>,
|
|
|
|
|
|
js::SystemAllocPolicy> ConstructorMap;
|
2018-01-19 03:59:58 +08:00
|
|
|
|
|
|
|
|
|
|
// Hashtable for custom element definitions in web components.
|
|
|
|
|
|
// Custom prototypes are stored in the compartment where
|
|
|
|
|
|
// registerElement was called.
|
|
|
|
|
|
DefinitionMap mCustomDefinitions;
|
|
|
|
|
|
|
2020-01-02 21:24:22 -05:00
|
|
|
|
// Hashtable for looking up definitions by using constructor as key.
|
|
|
|
|
|
// Custom elements' name are stored here and we need to lookup
|
|
|
|
|
|
// mCustomDefinitions again to get definitions.
|
|
|
|
|
|
ConstructorMap mConstructors;
|
|
|
|
|
|
|
2018-01-19 03:59:58 +08:00
|
|
|
|
typedef nsRefPtrHashtable<nsISupportsHashKey, Promise>
|
|
|
|
|
|
WhenDefinedPromiseMap;
|
|
|
|
|
|
WhenDefinedPromiseMap mWhenDefinedPromiseMap;
|
2020-01-02 21:24:22 -05:00
|
|
|
|
|
2018-01-19 03:59:58 +08:00
|
|
|
|
// The "upgrade candidates map" from the web components spec. Maps from a
|
|
|
|
|
|
// namespace id and local name to a list of elements to upgrade if that
|
|
|
|
|
|
// element is registered as a custom element.
|
|
|
|
|
|
CandidateMap mCandidatesMap;
|
|
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsPIDOMWindowInner> mWindow;
|
|
|
|
|
|
|
|
|
|
|
|
// It is used to prevent reentrant invocations of element definition.
|
|
|
|
|
|
bool mIsCustomDefinitionRunning;
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
class MOZ_RAII AutoSetRunningFlag final {
|
|
|
|
|
|
public:
|
|
|
|
|
|
explicit AutoSetRunningFlag(CustomElementRegistry* aRegistry)
|
|
|
|
|
|
: mRegistry(aRegistry)
|
|
|
|
|
|
{
|
|
|
|
|
|
MOZ_ASSERT(!mRegistry->mIsCustomDefinitionRunning,
|
|
|
|
|
|
"IsCustomDefinitionRunning flag should be initially false");
|
|
|
|
|
|
mRegistry->mIsCustomDefinitionRunning = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
~AutoSetRunningFlag() {
|
|
|
|
|
|
mRegistry->mIsCustomDefinitionRunning = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
CustomElementRegistry* mRegistry;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
nsISupports* GetParentObject() const;
|
|
|
|
|
|
|
|
|
|
|
|
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
|
|
|
|
|
|
|
|
|
|
|
void Define(const nsAString& aName, Function& aFunctionConstructor,
|
|
|
|
|
|
const ElementDefinitionOptions& aOptions, ErrorResult& aRv);
|
|
|
|
|
|
|
|
|
|
|
|
void Get(JSContext* cx, const nsAString& name,
|
|
|
|
|
|
JS::MutableHandle<JS::Value> aRetVal);
|
|
|
|
|
|
|
|
|
|
|
|
already_AddRefed<Promise> WhenDefined(const nsAString& aName, ErrorResult& aRv);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2020-01-02 22:04:11 -05:00
|
|
|
|
class MOZ_RAII AutoCEReaction final {
|
|
|
|
|
|
public:
|
2020-01-03 22:18:55 -05:00
|
|
|
|
explicit AutoCEReaction(CustomElementReactionsStack* aReactionsStack)
|
|
|
|
|
|
: mReactionsStack(aReactionsStack) {
|
|
|
|
|
|
mReactionsStack->CreateAndPushElementQueue();
|
2020-01-02 22:04:11 -05:00
|
|
|
|
}
|
|
|
|
|
|
~AutoCEReaction() {
|
2020-01-03 22:18:55 -05:00
|
|
|
|
mReactionsStack->PopAndInvokeElementQueue();
|
2020-01-02 22:04:11 -05:00
|
|
|
|
}
|
|
|
|
|
|
private:
|
2020-01-03 22:18:55 -05:00
|
|
|
|
RefPtr<CustomElementReactionsStack> mReactionsStack;
|
2020-01-02 22:04:11 -05:00
|
|
|
|
};
|
|
|
|
|
|
|
2018-01-19 03:59:58 +08:00
|
|
|
|
} // namespace dom
|
|
|
|
|
|
} // namespace mozilla
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif // mozilla_dom_CustomElementRegistry_h
|