mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-20 22:27:31 +09:00
Bug 1315885 - Part 4: Implement callback reaction for custom element reactions.
Note: Skipped SyncInvokeReactions since it is removed in CE v1, waste of time. Tag UXP Issue #1344
This commit is contained in:
parent
931b14f847
commit
34dd7065f5
5 changed files with 101 additions and 138 deletions
|
|
@ -92,26 +92,12 @@ 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
|
||||||
|
|
||||||
|
|
@ -128,7 +114,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()) {
|
||||||
nsAutoPtr<LifecycleCallbacks>& callbacks = iter.UserData()->mCallbacks;
|
auto& 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,
|
||||||
|
|
@ -191,43 +177,6 @@ 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)
|
||||||
|
|
@ -237,12 +186,6 @@ 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()
|
||||||
|
|
@ -346,14 +289,15 @@ 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.
|
||||||
EnqueueLifecycleCallback(nsIDocument::eCreated, aElement, nullptr, definition);
|
// We make it synchronously for createElement/createElementNS in order to
|
||||||
|
// pass tests. It'll be removed when we deprecate custom elements v0.
|
||||||
|
// SyncInvokeReactions(nsIDocument::eCreated, aElement, definition);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
UniquePtr<CustomElementCallback>
|
||||||
CustomElementRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
|
CustomElementRegistry::CreateCustomElementCallback(
|
||||||
Element* aCustomElement,
|
nsIDocument::ElementCallbackType aType, Element* aCustomElement,
|
||||||
LifecycleCallbackArgs* aArgs,
|
LifecycleCallbackArgs* aArgs, CustomElementDefinition* aDefinition)
|
||||||
CustomElementDefinition* aDefinition)
|
|
||||||
{
|
{
|
||||||
RefPtr<CustomElementData> elementData = aCustomElement->GetCustomElementData();
|
RefPtr<CustomElementData> elementData = aCustomElement->GetCustomElementData();
|
||||||
MOZ_ASSERT(elementData, "CustomElementData should exist");
|
MOZ_ASSERT(elementData, "CustomElementData should exist");
|
||||||
|
|
@ -372,7 +316,7 @@ CustomElementRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType
|
||||||
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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -406,7 +350,7 @@ CustomElementRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType
|
||||||
|
|
||||||
// If there is no such callback, stop.
|
// If there is no such callback, stop.
|
||||||
if (!func) {
|
if (!func) {
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aType == nsIDocument::eCreated) {
|
if (aType == nsIDocument::eCreated) {
|
||||||
|
|
@ -414,54 +358,41 @@ CustomElementRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType
|
||||||
} 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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add CALLBACK to ELEMENT's callback queue.
|
// Add CALLBACK to ELEMENT's callback queue.
|
||||||
CustomElementCallback* callback = new CustomElementCallback(aCustomElement,
|
auto callback =
|
||||||
aType,
|
MakeUnique<CustomElementCallback>(aCustomElement, aType, func, elementData);
|
||||||
func,
|
|
||||||
elementData);
|
|
||||||
// Ownership of callback is taken by mCallbackQueue.
|
|
||||||
elementData->mCallbackQueue.AppendElement(callback);
|
|
||||||
if (aArgs) {
|
if (aArgs) {
|
||||||
callback->SetArgs(*aArgs);
|
callback->SetArgs(*aArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!elementData->mElementIsBeingCreated) {
|
return Move(callback);
|
||||||
CustomElementData* lastData =
|
}
|
||||||
sProcessingStack->SafeLastElement(nullptr);
|
|
||||||
|
|
||||||
// A new element queue needs to be pushed if the queue at the
|
void
|
||||||
// top of the stack is associated with another microtask level.
|
CustomElementRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
|
||||||
bool shouldPushElementQueue =
|
Element* aCustomElement,
|
||||||
(!lastData || lastData->mAssociatedMicroTask <
|
LifecycleCallbackArgs* aArgs,
|
||||||
static_cast<int32_t>(nsContentUtils::MicroTaskLevel()));
|
CustomElementDefinition* aDefinition)
|
||||||
|
{
|
||||||
// Push a new element queue onto the processing stack when appropriate
|
auto callback =
|
||||||
// (when we enter a new microtask).
|
CreateCustomElementCallback(aType, aCustomElement, aArgs, aDefinition);
|
||||||
if (shouldPushElementQueue) {
|
if (!callback) {
|
||||||
// Push a sentinel value on the processing stack to mark the
|
return;
|
||||||
// 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(&CustomElementRegistry::ProcessTopElementQueue);
|
|
||||||
nsContentUtils::AddScriptRunner(runnable);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DocGroup* docGroup = mWindow->GetDocGroup();
|
||||||
|
if (!docGroup) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomElementReactionsStack* reactionsStack =
|
||||||
|
docGroup->CustomElementReactionsStack();
|
||||||
|
reactionsStack->EnqueueCallbackReaction(this, aCustomElement, aDefinition,
|
||||||
|
Move(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -933,6 +864,16 @@ 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)
|
||||||
|
|
@ -1026,5 +967,14 @@ 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
|
||||||
|
|
|
||||||
|
|
@ -84,23 +84,14 @@ 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.
|
||||||
|
|
@ -109,10 +100,7 @@ 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<nsAutoPtr<CustomElementReaction>, 3> mReactionQueue;
|
AutoTArray<UniquePtr<CustomElementReaction>, 3> mReactionQueue;
|
||||||
|
|
||||||
// Empties the callback queue.
|
|
||||||
void RunCallbackQueue();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual ~CustomElementData() {}
|
virtual ~CustomElementData() {}
|
||||||
|
|
@ -142,7 +130,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.
|
||||||
nsAutoPtr<mozilla::dom::LifecycleCallbacks> mCallbacks;
|
UniquePtr<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
|
||||||
|
|
@ -163,10 +151,13 @@ 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;
|
||||||
|
|
@ -186,6 +177,27 @@ 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
|
||||||
{
|
{
|
||||||
|
|
@ -211,6 +223,15 @@ 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();
|
||||||
|
|
@ -276,10 +297,6 @@ 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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -312,6 +329,10 @@ public:
|
||||||
private:
|
private:
|
||||||
~CustomElementRegistry();
|
~CustomElementRegistry();
|
||||||
|
|
||||||
|
UniquePtr<CustomElementCallback> CreateCustomElementCallback(
|
||||||
|
nsIDocument::ElementCallbackType aType, Element* aCustomElement,
|
||||||
|
LifecycleCallbackArgs* aArgs, 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.
|
||||||
|
|
@ -358,14 +379,6 @@ 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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -584,8 +584,10 @@ FragmentOrElement::nsDOMSlots::Traverse(nsCycleCollectionTraversalCallback &cb)
|
||||||
|
|
||||||
if (mExtendedSlots->mCustomElementData) {
|
if (mExtendedSlots->mCustomElementData) {
|
||||||
for (uint32_t i = 0;
|
for (uint32_t i = 0;
|
||||||
i < mExtendedSlots->mCustomElementData->mCallbackQueue.Length(); i++) {
|
i < mExtendedSlots->mCustomElementData->mReactionQueue.Length(); i++) {
|
||||||
mExtendedSlots->mCustomElementData->mCallbackQueue[i]->Traverse(cb);
|
if (mExtendedSlots->mCustomElementData->mReactionQueue[i]) {
|
||||||
|
mExtendedSlots->mCustomElementData->mReactionQueue[i]->Traverse(cb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,8 @@ 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, false, "While element is being created, element should not be added to the current element callback queue.");
|
is(attributeChangedCallbackCalled, true, "While element is being created, element should be added to the current element callback queue.");
|
||||||
|
runNextTest();
|
||||||
};
|
};
|
||||||
|
|
||||||
p.attributeChangedCallback = function(name, oldValue, newValue) {
|
p.attributeChangedCallback = function(name, oldValue, newValue) {
|
||||||
|
|
@ -36,7 +37,6 @@ 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 });
|
||||||
|
|
|
||||||
|
|
@ -412,8 +412,6 @@ nsLayoutStatics::Shutdown()
|
||||||
|
|
||||||
DisplayItemClip::Shutdown();
|
DisplayItemClip::Shutdown();
|
||||||
|
|
||||||
CustomElementRegistry::XPCOMShutdown();
|
|
||||||
|
|
||||||
CacheObserver::Shutdown();
|
CacheObserver::Shutdown();
|
||||||
|
|
||||||
PromiseDebugging::Shutdown();
|
PromiseDebugging::Shutdown();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue