diff options
Diffstat (limited to 'dom/base/CustomElementRegistry.cpp')
-rw-r--r-- | dom/base/CustomElementRegistry.cpp | 160 |
1 files changed, 55 insertions, 105 deletions
diff --git a/dom/base/CustomElementRegistry.cpp b/dom/base/CustomElementRegistry.cpp index 6419c1425..bd26e4ff3 100644 --- a/dom/base/CustomElementRegistry.cpp +++ b/dom/base/CustomElementRegistry.cpp @@ -92,26 +92,12 @@ CustomElementData::CustomElementData(nsIAtom* aType) CustomElementData::CustomElementData(nsIAtom* aType, State aState) : mType(aType) - , mCurrentCallback(-1) , mElementIsBeingCreated(false) , mCreatedCallbackInvoked(true) - , mAssociatedMicroTask(-1) , 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 @@ -128,7 +114,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CustomElementRegistry) 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()) { NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, @@ -191,43 +177,6 @@ CustomElementRegistry::IsCustomElementEnabled(JSContext* aCx, JSObject* aObject) 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) : mWindow(aWindow) , mIsCustomDefinitionRunning(false) @@ -237,12 +186,6 @@ CustomElementRegistry::CustomElementRegistry(nsPIDOMWindowInner* aWindow) MOZ_ALWAYS_TRUE(mConstructors.init()); mozilla::HoldJSObjects(this); - - if (!sProcessingStack) { - sProcessingStack.emplace(); - // Add the base queue sentinel to the processing stack. - sProcessingStack->AppendElement((CustomElementData*) nullptr); - } } CustomElementRegistry::~CustomElementRegistry() @@ -346,14 +289,15 @@ CustomElementRegistry::SetupCustomElement(Element* aElement, // Enqueuing the created callback will set the CustomElementData on the // 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 -CustomElementRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType, - Element* aCustomElement, - LifecycleCallbackArgs* aArgs, - CustomElementDefinition* aDefinition) +UniquePtr<CustomElementCallback> +CustomElementRegistry::CreateCustomElementCallback( + nsIDocument::ElementCallbackType aType, Element* aCustomElement, + LifecycleCallbackArgs* aArgs, CustomElementDefinition* aDefinition) { RefPtr<CustomElementData> elementData = aCustomElement->GetCustomElementData(); MOZ_ASSERT(elementData, "CustomElementData should exist"); @@ -372,7 +316,7 @@ CustomElementRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType if (!definition || definition->mLocalName != info->NameAtom()) { // Trying to enqueue a callback for an element that is not // 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 (!func) { - return; + return nullptr; } if (aType == nsIDocument::eCreated) { @@ -414,54 +358,41 @@ CustomElementRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType } else if (!elementData->mCreatedCallbackInvoked) { // Callbacks other than created callback must not be enqueued // until after the created callback has been invoked. - return; + return nullptr; } // Add CALLBACK to ELEMENT's callback queue. - CustomElementCallback* callback = new CustomElementCallback(aCustomElement, - aType, - func, - elementData); - // Ownership of callback is taken by mCallbackQueue. - elementData->mCallbackQueue.AppendElement(callback); + auto callback = + MakeUnique<CustomElementCallback>(aCustomElement, aType, func, elementData); + if (aArgs) { callback->SetArgs(*aArgs); } - if (!elementData->mElementIsBeingCreated) { - CustomElementData* lastData = - sProcessingStack->SafeLastElement(nullptr); - - // A new element queue needs to be pushed if the queue at the - // top of the stack is associated with another microtask level. - bool shouldPushElementQueue = - (!lastData || lastData->mAssociatedMicroTask < - static_cast<int32_t>(nsContentUtils::MicroTaskLevel())); - - // Push a new element queue onto the processing stack when appropriate - // (when we enter a new microtask). - if (shouldPushElementQueue) { - // Push a sentinel value on the processing stack to mark the - // boundary between the element queues. - sProcessingStack->AppendElement((CustomElementData*) nullptr); - } + return Move(callback); +} - 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); - } +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 @@ -934,6 +865,16 @@ CustomElementReactionsStack::EnqueueUpgradeReaction(CustomElementRegistry* aRegi } void +CustomElementReactionsStack::EnqueueCallbackReaction(CustomElementRegistry* aRegistry, + Element* aElement, + CustomElementDefinition* aDefinition, + UniquePtr<CustomElementCallback> aCustomElementCallback) +{ + Enqueue(aElement, new CustomElementCallbackReaction(aRegistry, aDefinition, + Move(aCustomElementCallback))); +} + +void CustomElementReactionsStack::Enqueue(Element* aElement, CustomElementReaction* aReaction) { @@ -1026,5 +967,14 @@ CustomElementUpgradeReaction::Invoke(Element* aElement) mRegistry->Upgrade(aElement, mDefinition); } +//----------------------------------------------------- +// CustomElementCallbackReaction + +/* virtual */ void +CustomElementCallbackReaction::Invoke(Element* aElement) +{ + mCustomElementCallback->Call(); +} + } // namespace dom } // namespace mozilla |