зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 4 changesets (bug 1315885) for merge conflicts with bug 1377993.
Backed out changeset c6dcdfe7ac54 (bug 1315885) Backed out changeset c8bc78492b81 (bug 1315885) Backed out changeset 7ba49d85f30c (bug 1315885) Backed out changeset d592ae3b61bf (bug 1315885)
This commit is contained in:
Родитель
5e6827da6d
Коммит
f142e0a216
|
@ -55,10 +55,6 @@ CustomElementCallback::Call()
|
||||||
mArgs.name, mArgs.oldValue, mArgs.newValue, rv);
|
mArgs.name, mArgs.oldValue, mArgs.newValue, rv);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If callbacks throw exceptions, it'll be handled and reported in
|
|
||||||
// Lifecycle*Callback::Call function.
|
|
||||||
rv.SuppressException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -92,12 +88,26 @@ CustomElementData::CustomElementData(nsIAtom* aType)
|
||||||
|
|
||||||
CustomElementData::CustomElementData(nsIAtom* aType, State aState)
|
CustomElementData::CustomElementData(nsIAtom* aType, State aState)
|
||||||
: mType(aType)
|
: mType(aType)
|
||||||
|
, mCurrentCallback(-1)
|
||||||
, mElementIsBeingCreated(false)
|
, mElementIsBeingCreated(false)
|
||||||
, mCreatedCallbackInvoked(true)
|
, mCreatedCallbackInvoked(true)
|
||||||
|
, mAssociatedMicroTask(-1)
|
||||||
, mState(aState)
|
, mState(aState)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CustomElementData::RunCallbackQueue()
|
||||||
|
{
|
||||||
|
// Note: It's possible to re-enter this method.
|
||||||
|
while (static_cast<uint32_t>(++mCurrentCallback) < mCallbackQueue.Length()) {
|
||||||
|
mCallbackQueue[mCurrentCallback]->Call();
|
||||||
|
}
|
||||||
|
|
||||||
|
mCallbackQueue.Clear();
|
||||||
|
mCurrentCallback = -1;
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------
|
//-----------------------------------------------------
|
||||||
// CustomElementRegistry
|
// CustomElementRegistry
|
||||||
|
|
||||||
|
@ -114,7 +124,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CustomElementRegistry)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CustomElementRegistry)
|
||||||
for (auto iter = tmp->mCustomDefinitions.Iter(); !iter.Done(); iter.Next()) {
|
for (auto iter = tmp->mCustomDefinitions.Iter(); !iter.Done(); iter.Next()) {
|
||||||
auto& callbacks = iter.UserData()->mCallbacks;
|
nsAutoPtr<LifecycleCallbacks>& callbacks = iter.UserData()->mCallbacks;
|
||||||
|
|
||||||
if (callbacks->mAttributeChangedCallback.WasPassed()) {
|
if (callbacks->mAttributeChangedCallback.WasPassed()) {
|
||||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
|
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
|
||||||
|
@ -178,6 +188,43 @@ CustomElementRegistry::IsCustomElementEnabled(JSContext* aCx, JSObject* aObject)
|
||||||
nsContentUtils::IsWebComponentsEnabled();
|
nsContentUtils::IsWebComponentsEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */ void
|
||||||
|
CustomElementRegistry::ProcessTopElementQueue()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
|
||||||
|
|
||||||
|
nsTArray<RefPtr<CustomElementData>>& stack = *sProcessingStack;
|
||||||
|
uint32_t firstQueue = stack.LastIndexOf((CustomElementData*) nullptr);
|
||||||
|
|
||||||
|
for (uint32_t i = firstQueue + 1; i < stack.Length(); ++i) {
|
||||||
|
// Callback queue may have already been processed in an earlier
|
||||||
|
// element queue or in an element queue that was popped
|
||||||
|
// off more recently.
|
||||||
|
if (stack[i]->mAssociatedMicroTask != -1) {
|
||||||
|
stack[i]->RunCallbackQueue();
|
||||||
|
stack[i]->mAssociatedMicroTask = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this was actually the base element queue, don't bother trying to pop
|
||||||
|
// the first "queue" marker (sentinel).
|
||||||
|
if (firstQueue != 0) {
|
||||||
|
stack.SetLength(firstQueue);
|
||||||
|
} else {
|
||||||
|
// Don't pop sentinel for base element queue.
|
||||||
|
stack.SetLength(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ void
|
||||||
|
CustomElementRegistry::XPCOMShutdown()
|
||||||
|
{
|
||||||
|
sProcessingStack.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ Maybe<nsTArray<RefPtr<CustomElementData>>>
|
||||||
|
CustomElementRegistry::sProcessingStack;
|
||||||
|
|
||||||
CustomElementRegistry::CustomElementRegistry(nsPIDOMWindowInner* aWindow)
|
CustomElementRegistry::CustomElementRegistry(nsPIDOMWindowInner* aWindow)
|
||||||
: mWindow(aWindow)
|
: mWindow(aWindow)
|
||||||
, mIsCustomDefinitionRunning(false)
|
, mIsCustomDefinitionRunning(false)
|
||||||
|
@ -187,6 +234,12 @@ CustomElementRegistry::CustomElementRegistry(nsPIDOMWindowInner* aWindow)
|
||||||
MOZ_ALWAYS_TRUE(mConstructors.init());
|
MOZ_ALWAYS_TRUE(mConstructors.init());
|
||||||
|
|
||||||
mozilla::HoldJSObjects(this);
|
mozilla::HoldJSObjects(this);
|
||||||
|
|
||||||
|
if (!sProcessingStack) {
|
||||||
|
sProcessingStack.emplace();
|
||||||
|
// Add the base queue sentinel to the processing stack.
|
||||||
|
sProcessingStack->AppendElement((CustomElementData*) nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomElementRegistry::~CustomElementRegistry()
|
CustomElementRegistry::~CustomElementRegistry()
|
||||||
|
@ -290,15 +343,14 @@ CustomElementRegistry::SetupCustomElement(Element* aElement,
|
||||||
|
|
||||||
// Enqueuing the created callback will set the CustomElementData on the
|
// Enqueuing the created callback will set the CustomElementData on the
|
||||||
// element, causing prototype swizzling to occur in Element::WrapObject.
|
// element, causing prototype swizzling to occur in Element::WrapObject.
|
||||||
// We make it synchronously for createElement/createElementNS in order to
|
EnqueueLifecycleCallback(nsIDocument::eCreated, aElement, nullptr, definition);
|
||||||
// pass tests. It'll be removed when we deprecate custom elements v0.
|
|
||||||
SyncInvokeReactions(nsIDocument::eCreated, aElement, definition);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UniquePtr<CustomElementCallback>
|
void
|
||||||
CustomElementRegistry::CreateCustomElementCallback(
|
CustomElementRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
|
||||||
nsIDocument::ElementCallbackType aType, Element* aCustomElement,
|
Element* aCustomElement,
|
||||||
LifecycleCallbackArgs* aArgs, CustomElementDefinition* aDefinition)
|
LifecycleCallbackArgs* aArgs,
|
||||||
|
CustomElementDefinition* aDefinition)
|
||||||
{
|
{
|
||||||
RefPtr<CustomElementData> elementData = aCustomElement->GetCustomElementData();
|
RefPtr<CustomElementData> elementData = aCustomElement->GetCustomElementData();
|
||||||
MOZ_ASSERT(elementData, "CustomElementData should exist");
|
MOZ_ASSERT(elementData, "CustomElementData should exist");
|
||||||
|
@ -317,7 +369,7 @@ CustomElementRegistry::CreateCustomElementCallback(
|
||||||
if (!definition || definition->mLocalName != info->NameAtom()) {
|
if (!definition || definition->mLocalName != info->NameAtom()) {
|
||||||
// Trying to enqueue a callback for an element that is not
|
// Trying to enqueue a callback for an element that is not
|
||||||
// a custom element. We are done, nothing to do.
|
// a custom element. We are done, nothing to do.
|
||||||
return nullptr;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,7 +403,7 @@ CustomElementRegistry::CreateCustomElementCallback(
|
||||||
|
|
||||||
// If there is no such callback, stop.
|
// If there is no such callback, stop.
|
||||||
if (!func) {
|
if (!func) {
|
||||||
return nullptr;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aType == nsIDocument::eCreated) {
|
if (aType == nsIDocument::eCreated) {
|
||||||
|
@ -359,62 +411,55 @@ CustomElementRegistry::CreateCustomElementCallback(
|
||||||
} else if (!elementData->mCreatedCallbackInvoked) {
|
} else if (!elementData->mCreatedCallbackInvoked) {
|
||||||
// Callbacks other than created callback must not be enqueued
|
// Callbacks other than created callback must not be enqueued
|
||||||
// until after the created callback has been invoked.
|
// until after the created callback has been invoked.
|
||||||
return nullptr;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add CALLBACK to ELEMENT's callback queue.
|
// Add CALLBACK to ELEMENT's callback queue.
|
||||||
auto callback =
|
CustomElementCallback* callback = new CustomElementCallback(aCustomElement,
|
||||||
MakeUnique<CustomElementCallback>(aCustomElement, aType, func, elementData);
|
aType,
|
||||||
|
func,
|
||||||
|
elementData);
|
||||||
|
// Ownership of callback is taken by mCallbackQueue.
|
||||||
|
elementData->mCallbackQueue.AppendElement(callback);
|
||||||
if (aArgs) {
|
if (aArgs) {
|
||||||
callback->SetArgs(*aArgs);
|
callback->SetArgs(*aArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Move(callback);
|
if (!elementData->mElementIsBeingCreated) {
|
||||||
}
|
CustomElementData* lastData =
|
||||||
|
sProcessingStack->SafeLastElement(nullptr);
|
||||||
|
|
||||||
void
|
// A new element queue needs to be pushed if the queue at the
|
||||||
CustomElementRegistry::SyncInvokeReactions(nsIDocument::ElementCallbackType aType,
|
// top of the stack is associated with another microtask level.
|
||||||
Element* aCustomElement,
|
bool shouldPushElementQueue =
|
||||||
CustomElementDefinition* aDefinition)
|
(!lastData || lastData->mAssociatedMicroTask <
|
||||||
{
|
static_cast<int32_t>(nsContentUtils::MicroTaskLevel()));
|
||||||
auto callback = CreateCustomElementCallback(aType, aCustomElement, nullptr,
|
|
||||||
aDefinition);
|
// Push a new element queue onto the processing stack when appropriate
|
||||||
if (!callback) {
|
// (when we enter a new microtask).
|
||||||
return;
|
if (shouldPushElementQueue) {
|
||||||
|
// Push a sentinel value on the processing stack to mark the
|
||||||
|
// boundary between the element queues.
|
||||||
|
sProcessingStack->AppendElement((CustomElementData*) nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
sProcessingStack->AppendElement(elementData);
|
||||||
|
elementData->mAssociatedMicroTask =
|
||||||
|
static_cast<int32_t>(nsContentUtils::MicroTaskLevel());
|
||||||
|
|
||||||
|
// Add a script runner to pop and process the element queue at
|
||||||
|
// the top of the processing stack.
|
||||||
|
if (shouldPushElementQueue) {
|
||||||
|
// Lifecycle callbacks enqueued by user agent implementation
|
||||||
|
// should be invoked prior to returning control back to script.
|
||||||
|
// Create a script runner to process the top of the processing
|
||||||
|
// stack as soon as it is safe to run script.
|
||||||
|
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction(
|
||||||
|
"dom::CustomElementRegistry::EnqueueLifecycleCallback",
|
||||||
|
&CustomElementRegistry::ProcessTopElementQueue);
|
||||||
|
nsContentUtils::AddScriptRunner(runnable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UniquePtr<CustomElementReaction> reaction(Move(
|
|
||||||
MakeUnique<CustomElementCallbackReaction>(this, aDefinition,
|
|
||||||
Move(callback))));
|
|
||||||
|
|
||||||
RefPtr<SyncInvokeReactionRunnable> runnable =
|
|
||||||
new SyncInvokeReactionRunnable(Move(reaction), aCustomElement);
|
|
||||||
|
|
||||||
nsContentUtils::AddScriptRunner(runnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CustomElementRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
|
|
||||||
Element* aCustomElement,
|
|
||||||
LifecycleCallbackArgs* aArgs,
|
|
||||||
CustomElementDefinition* aDefinition)
|
|
||||||
{
|
|
||||||
auto callback =
|
|
||||||
CreateCustomElementCallback(aType, aCustomElement, aArgs, aDefinition);
|
|
||||||
if (!callback) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DocGroup* docGroup = mWindow->GetDocGroup();
|
|
||||||
if (!docGroup) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomElementReactionsStack* reactionsStack =
|
|
||||||
docGroup->CustomElementReactionsStack();
|
|
||||||
reactionsStack->EnqueueCallbackReaction(this, aCustomElement, aDefinition,
|
|
||||||
Move(callback));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -898,16 +943,6 @@ CustomElementReactionsStack::EnqueueUpgradeReaction(CustomElementRegistry* aRegi
|
||||||
Enqueue(aElement, new CustomElementUpgradeReaction(aRegistry, aDefinition));
|
Enqueue(aElement, new CustomElementUpgradeReaction(aRegistry, aDefinition));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
CustomElementReactionsStack::EnqueueCallbackReaction(CustomElementRegistry* aRegistry,
|
|
||||||
Element* aElement,
|
|
||||||
CustomElementDefinition* aDefinition,
|
|
||||||
UniquePtr<CustomElementCallback> aCustomElementCallback)
|
|
||||||
{
|
|
||||||
Enqueue(aElement, new CustomElementCallbackReaction(aRegistry, aDefinition,
|
|
||||||
Move(aCustomElementCallback)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CustomElementReactionsStack::Enqueue(Element* aElement,
|
CustomElementReactionsStack::Enqueue(Element* aElement,
|
||||||
CustomElementReaction* aReaction)
|
CustomElementReaction* aReaction)
|
||||||
|
@ -949,7 +984,6 @@ CustomElementReactionsStack::InvokeBackupQueue()
|
||||||
void
|
void
|
||||||
CustomElementReactionsStack::InvokeReactions(ElementQueue& aElementQueue)
|
CustomElementReactionsStack::InvokeReactions(ElementQueue& aElementQueue)
|
||||||
{
|
{
|
||||||
// Note: It's possible to re-enter this method.
|
|
||||||
for (uint32_t i = 0; i < aElementQueue.Length(); ++i) {
|
for (uint32_t i = 0; i < aElementQueue.Length(); ++i) {
|
||||||
nsCOMPtr<Element> element = do_QueryReferent(aElementQueue[i]);
|
nsCOMPtr<Element> element = do_QueryReferent(aElementQueue[i]);
|
||||||
|
|
||||||
|
@ -960,14 +994,10 @@ CustomElementReactionsStack::InvokeReactions(ElementQueue& aElementQueue)
|
||||||
RefPtr<CustomElementData> elementData = element->GetCustomElementData();
|
RefPtr<CustomElementData> elementData = element->GetCustomElementData();
|
||||||
MOZ_ASSERT(elementData, "CustomElementData should exist");
|
MOZ_ASSERT(elementData, "CustomElementData should exist");
|
||||||
|
|
||||||
auto& reactions = elementData->mReactionQueue;
|
nsTArray<nsAutoPtr<CustomElementReaction>>& reactions =
|
||||||
|
elementData->mReactionQueue;
|
||||||
for (uint32_t j = 0; j < reactions.Length(); ++j) {
|
for (uint32_t j = 0; j < reactions.Length(); ++j) {
|
||||||
// Transfer the ownership of the entry due to reentrant invocation of
|
reactions.ElementAt(j)->Invoke(element);
|
||||||
// this funciton. The entry will be removed when bug 1379573 is landed.
|
|
||||||
auto reaction(Move(reactions.ElementAt(j)));
|
|
||||||
if (reaction) {
|
|
||||||
reaction->Invoke(element);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
reactions.Clear();
|
reactions.Clear();
|
||||||
}
|
}
|
||||||
|
@ -1002,14 +1032,5 @@ CustomElementUpgradeReaction::Invoke(Element* aElement)
|
||||||
mRegistry->Upgrade(aElement, mDefinition);
|
mRegistry->Upgrade(aElement, mDefinition);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------
|
|
||||||
// CustomElementCallbackReaction
|
|
||||||
|
|
||||||
/* virtual */ void
|
|
||||||
CustomElementCallbackReaction::Invoke(Element* aElement)
|
|
||||||
{
|
|
||||||
mCustomElementCallback->Call();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -85,14 +85,23 @@ struct CustomElementData
|
||||||
|
|
||||||
explicit CustomElementData(nsIAtom* aType);
|
explicit CustomElementData(nsIAtom* aType);
|
||||||
CustomElementData(nsIAtom* aType, State aState);
|
CustomElementData(nsIAtom* aType, State aState);
|
||||||
|
// Objects in this array are transient and empty after each microtask
|
||||||
|
// checkpoint.
|
||||||
|
nsTArray<nsAutoPtr<CustomElementCallback>> mCallbackQueue;
|
||||||
// Custom element type, for <button is="x-button"> or <x-button>
|
// Custom element type, for <button is="x-button"> or <x-button>
|
||||||
// this would be x-button.
|
// this would be x-button.
|
||||||
nsCOMPtr<nsIAtom> mType;
|
nsCOMPtr<nsIAtom> mType;
|
||||||
|
// The callback that is next to be processed upon calling RunCallbackQueue.
|
||||||
|
int32_t mCurrentCallback;
|
||||||
// Element is being created flag as described in the custom elements spec.
|
// Element is being created flag as described in the custom elements spec.
|
||||||
bool mElementIsBeingCreated;
|
bool mElementIsBeingCreated;
|
||||||
// Flag to determine if the created callback has been invoked, thus it
|
// Flag to determine if the created callback has been invoked, thus it
|
||||||
// determines if other callbacks can be enqueued.
|
// determines if other callbacks can be enqueued.
|
||||||
bool mCreatedCallbackInvoked;
|
bool mCreatedCallbackInvoked;
|
||||||
|
// The microtask level associated with the callbacks in the callback queue,
|
||||||
|
// 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.
|
// Custom element state as described in the custom element spec.
|
||||||
State mState;
|
State mState;
|
||||||
// custom element reaction queue as described in the custom element spec.
|
// custom element reaction queue as described in the custom element spec.
|
||||||
|
@ -101,7 +110,10 @@ struct CustomElementData
|
||||||
// appended, removed, or replaced.
|
// appended, removed, or replaced.
|
||||||
// There are 3 reactions in reaction queue when doing upgrade operation,
|
// There are 3 reactions in reaction queue when doing upgrade operation,
|
||||||
// e.g., create an element, insert a node.
|
// e.g., create an element, insert a node.
|
||||||
AutoTArray<UniquePtr<CustomElementReaction>, 3> mReactionQueue;
|
AutoTArray<nsAutoPtr<CustomElementReaction>, 3> mReactionQueue;
|
||||||
|
|
||||||
|
// Empties the callback queue.
|
||||||
|
void RunCallbackQueue();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual ~CustomElementData() {}
|
virtual ~CustomElementData() {}
|
||||||
|
@ -131,7 +143,7 @@ struct CustomElementDefinition
|
||||||
JS::Heap<JSObject *> mPrototype;
|
JS::Heap<JSObject *> mPrototype;
|
||||||
|
|
||||||
// The lifecycle callbacks to call for this custom element.
|
// The lifecycle callbacks to call for this custom element.
|
||||||
UniquePtr<mozilla::dom::LifecycleCallbacks> mCallbacks;
|
nsAutoPtr<mozilla::dom::LifecycleCallbacks> mCallbacks;
|
||||||
|
|
||||||
// A construction stack.
|
// A construction stack.
|
||||||
// TODO: Bug 1287348 - Implement construction stack for upgrading an element
|
// TODO: Bug 1287348 - Implement construction stack for upgrading an element
|
||||||
|
@ -152,13 +164,10 @@ public:
|
||||||
: mRegistry(aRegistry)
|
: mRegistry(aRegistry)
|
||||||
, mDefinition(aDefinition)
|
, mDefinition(aDefinition)
|
||||||
{
|
{
|
||||||
}
|
};
|
||||||
|
|
||||||
virtual ~CustomElementReaction() = default;
|
virtual ~CustomElementReaction() = default;
|
||||||
virtual void Invoke(Element* aElement) = 0;
|
virtual void Invoke(Element* aElement) = 0;
|
||||||
virtual void Traverse(nsCycleCollectionTraversalCallback& aCb) const
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CustomElementRegistry* mRegistry;
|
CustomElementRegistry* mRegistry;
|
||||||
|
@ -178,27 +187,6 @@ private:
|
||||||
virtual void Invoke(Element* aElement) override;
|
virtual void Invoke(Element* aElement) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
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:
|
|
||||||
virtual void Invoke(Element* aElement) override;
|
|
||||||
UniquePtr<CustomElementCallback> mCustomElementCallback;
|
|
||||||
};
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/scripting.html#custom-element-reactions-stack
|
// https://html.spec.whatwg.org/multipage/scripting.html#custom-element-reactions-stack
|
||||||
class CustomElementReactionsStack
|
class CustomElementReactionsStack
|
||||||
{
|
{
|
||||||
|
@ -224,15 +212,6 @@ public:
|
||||||
Element* aElement,
|
Element* aElement,
|
||||||
CustomElementDefinition* aDefinition);
|
CustomElementDefinition* aDefinition);
|
||||||
|
|
||||||
/**
|
|
||||||
* 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);
|
|
||||||
|
|
||||||
// [CEReactions] Before executing the algorithm's steps
|
// [CEReactions] Before executing the algorithm's steps
|
||||||
// Push a new element queue onto the custom element reactions stack.
|
// Push a new element queue onto the custom element reactions stack.
|
||||||
void CreateAndPushElementQueue();
|
void CreateAndPushElementQueue();
|
||||||
|
@ -301,6 +280,10 @@ public:
|
||||||
static bool IsCustomElementEnabled(JSContext* aCx = nullptr,
|
static bool IsCustomElementEnabled(JSContext* aCx = nullptr,
|
||||||
JSObject* aObject = nullptr);
|
JSObject* aObject = nullptr);
|
||||||
|
|
||||||
|
static void ProcessTopElementQueue();
|
||||||
|
|
||||||
|
static void XPCOMShutdown();
|
||||||
|
|
||||||
explicit CustomElementRegistry(nsPIDOMWindowInner* aWindow);
|
explicit CustomElementRegistry(nsPIDOMWindowInner* aWindow);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -333,13 +316,6 @@ public:
|
||||||
private:
|
private:
|
||||||
~CustomElementRegistry();
|
~CustomElementRegistry();
|
||||||
|
|
||||||
UniquePtr<CustomElementCallback> CreateCustomElementCallback(
|
|
||||||
nsIDocument::ElementCallbackType aType, Element* aCustomElement,
|
|
||||||
LifecycleCallbackArgs* aArgs, CustomElementDefinition* aDefinition);
|
|
||||||
|
|
||||||
void SyncInvokeReactions(nsIDocument::ElementCallbackType aType,
|
|
||||||
Element* aCustomElement,
|
|
||||||
CustomElementDefinition* aDefinition);
|
|
||||||
/**
|
/**
|
||||||
* Registers an unresolved custom element that is a candidate for
|
* Registers an unresolved custom element that is a candidate for
|
||||||
* upgrade when the definition is registered via registerElement.
|
* upgrade when the definition is registered via registerElement.
|
||||||
|
@ -386,6 +362,14 @@ private:
|
||||||
|
|
||||||
nsCOMPtr<nsPIDOMWindowInner> mWindow;
|
nsCOMPtr<nsPIDOMWindowInner> mWindow;
|
||||||
|
|
||||||
|
// Array representing the processing stack in the custom elements
|
||||||
|
// specification. The processing stack is conceptually a stack of
|
||||||
|
// element queues. Each queue is represented by a sequence of
|
||||||
|
// CustomElementData in this array, separated by nullptr that
|
||||||
|
// represent the boundaries of the items in the stack. The first
|
||||||
|
// queue in the stack is the base element queue.
|
||||||
|
static mozilla::Maybe<nsTArray<RefPtr<CustomElementData>>> sProcessingStack;
|
||||||
|
|
||||||
// It is used to prevent reentrant invocations of element definition.
|
// It is used to prevent reentrant invocations of element definition.
|
||||||
bool mIsCustomDefinitionRunning;
|
bool mIsCustomDefinitionRunning;
|
||||||
|
|
||||||
|
@ -408,28 +392,6 @@ private:
|
||||||
CustomElementRegistry* mRegistry;
|
CustomElementRegistry* mRegistry;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SyncInvokeReactionRunnable : public mozilla::Runnable {
|
|
||||||
public:
|
|
||||||
SyncInvokeReactionRunnable(
|
|
||||||
UniquePtr<CustomElementReaction> aReaction, Element* aCustomElement)
|
|
||||||
: Runnable(
|
|
||||||
"dom::CustomElementRegistry::SyncInvokeReactionRunnable")
|
|
||||||
, mReaction(Move(aReaction))
|
|
||||||
, mCustomElement(aCustomElement)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHOD Run() override
|
|
||||||
{
|
|
||||||
mReaction->Invoke(mCustomElement);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
UniquePtr<CustomElementReaction> mReaction;
|
|
||||||
Element* mCustomElement;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
nsISupports* GetParentObject() const;
|
nsISupports* GetParentObject() const;
|
||||||
|
|
||||||
|
|
|
@ -711,10 +711,8 @@ FragmentOrElement::nsDOMSlots::Traverse(nsCycleCollectionTraversalCallback &cb,
|
||||||
cb.NoteXPCOMChild(mClassList.get());
|
cb.NoteXPCOMChild(mClassList.get());
|
||||||
|
|
||||||
if (mCustomElementData) {
|
if (mCustomElementData) {
|
||||||
for (uint32_t i = 0; i < mCustomElementData->mReactionQueue.Length(); i++) {
|
for (uint32_t i = 0; i < mCustomElementData->mCallbackQueue.Length(); i++) {
|
||||||
if (mCustomElementData->mReactionQueue[i]) {
|
mCustomElementData->mCallbackQueue[i]->Traverse(cb);
|
||||||
mCustomElementData->mReactionQueue[i]->Traverse(cb);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,8 +28,7 @@ function testChangeAttributeInCreatedCallback() {
|
||||||
createdCallbackCalled = true;
|
createdCallbackCalled = true;
|
||||||
is(attributeChangedCallbackCalled, false, "Attribute changed callback should not have been called prior to setting the attribute.");
|
is(attributeChangedCallbackCalled, false, "Attribute changed callback should not have been called prior to setting the attribute.");
|
||||||
this.setAttribute("foo", "bar");
|
this.setAttribute("foo", "bar");
|
||||||
is(attributeChangedCallbackCalled, true, "While element is being created, element should be added to the current element callback queue.");
|
is(attributeChangedCallbackCalled, false, "While element is being created, element should not be added to the current element callback queue.");
|
||||||
runNextTest();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
p.attributeChangedCallback = function(name, oldValue, newValue) {
|
p.attributeChangedCallback = function(name, oldValue, newValue) {
|
||||||
|
@ -37,6 +36,7 @@ function testChangeAttributeInCreatedCallback() {
|
||||||
is(attributeChangedCallbackCalled, false, "attributeChanged callback should only be called once in this tests.");
|
is(attributeChangedCallbackCalled, false, "attributeChanged callback should only be called once in this tests.");
|
||||||
is(newValue, "bar", "The new value should be 'bar'");
|
is(newValue, "bar", "The new value should be 'bar'");
|
||||||
attributeChangedCallbackCalled = true;
|
attributeChangedCallbackCalled = true;
|
||||||
|
runNextTest();
|
||||||
};
|
};
|
||||||
|
|
||||||
document.registerElement("x-one", { prototype: p });
|
document.registerElement("x-one", { prototype: p });
|
||||||
|
|
|
@ -17,7 +17,7 @@ interface ShadowRoot : DocumentFragment
|
||||||
HTMLCollection getElementsByTagName(DOMString localName);
|
HTMLCollection getElementsByTagName(DOMString localName);
|
||||||
HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
|
HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
|
||||||
HTMLCollection getElementsByClassName(DOMString classNames);
|
HTMLCollection getElementsByClassName(DOMString classNames);
|
||||||
[CEReactions, SetterThrows, TreatNullAs=EmptyString]
|
[SetterThrows,TreatNullAs=EmptyString]
|
||||||
attribute DOMString innerHTML;
|
attribute DOMString innerHTML;
|
||||||
readonly attribute Element host;
|
readonly attribute Element host;
|
||||||
readonly attribute ShadowRoot? olderShadowRoot;
|
readonly attribute ShadowRoot? olderShadowRoot;
|
||||||
|
|
|
@ -434,6 +434,8 @@ nsLayoutStatics::Shutdown()
|
||||||
|
|
||||||
DisplayItemClip::Shutdown();
|
DisplayItemClip::Shutdown();
|
||||||
|
|
||||||
|
CustomElementRegistry::XPCOMShutdown();
|
||||||
|
|
||||||
CacheObserver::Shutdown();
|
CacheObserver::Shutdown();
|
||||||
|
|
||||||
PromiseDebugging::Shutdown();
|
PromiseDebugging::Shutdown();
|
||||||
|
|
Загрузка…
Ссылка в новой задаче