From e3dce688344217b4133df6968f5572140e6163b7 Mon Sep 17 00:00:00 2001 From: Butkovits Atila Date: Wed, 10 Jun 2020 10:07:23 +0300 Subject: [PATCH] Backed out 3 changesets (bug 1643289, bug 1642949) for causing failure at test_headless_screenshot.html. CLOSED TREE Backed out changeset 98c420f73380 (bug 1643289) Backed out changeset 9447ea8910aa (bug 1643289) Backed out changeset 0c827da9d847 (bug 1642949) --- dom/base/CustomElementRegistry.cpp | 8 +-- dom/base/ResponsiveImageSelector.cpp | 2 +- dom/base/nsDOMMutationObserver.cpp | 7 +-- dom/base/nsPlainTextSerializer.cpp | 8 ++- dom/base/nsXMLContentSerializer.cpp | 2 +- dom/cache/AutoUtils.cpp | 3 +- dom/console/Console.cpp | 6 ++- dom/events/EventDispatcher.cpp | 5 +- dom/html/TextControlState.cpp | 3 +- dom/html/nsHTMLContentSink.cpp | 19 ++++--- dom/indexedDB/ActorsParent.cpp | 7 ++- .../agnostic/DummyMediaDataDecoder.cpp | 8 +-- dom/media/platforms/apple/AppleVTDecoder.cpp | 2 +- dom/media/webaudio/AudioNode.cpp | 14 ++++-- dom/media/webaudio/AudioNode.h | 4 -- dom/media/webaudio/AudioParam.cpp | 4 +- dom/plugins/base/nsNPAPIPluginInstance.cpp | 10 +++- dom/plugins/ipc/PluginModuleChild.cpp | 7 ++- dom/smil/SMILTimeContainer.cpp | 4 +- dom/smil/SMILTimeContainer.h | 3 +- dom/webbrowserpersist/nsWebBrowserPersist.cpp | 4 +- dom/workers/Queue.h | 4 +- dom/workers/RuntimeService.cpp | 2 +- dom/xml/nsXMLContentSink.cpp | 6 ++- dom/xslt/base/txStack.h | 4 +- dom/xslt/xslt/txExecutionState.cpp | 7 ++- dom/xslt/xslt/txStylesheetCompiler.cpp | 6 ++- editor/libeditor/TypeInState.cpp | 22 ++++++-- gfx/layers/ImageContainer.cpp | 5 +- gfx/layers/LayerSorter.cpp | 5 +- gfx/layers/wr/IpcResourceUpdateQueue.cpp | 6 ++- layout/base/PresShell.cpp | 6 ++- layout/base/nsBidiPresUtils.cpp | 2 +- layout/base/nsPresArena.cpp | 6 ++- layout/style/ServoStyleSet.cpp | 5 +- layout/svg/SVGTextFrame.cpp | 4 +- layout/tables/nsTableFrame.cpp | 2 +- netwerk/cache2/CacheIndexIterator.cpp | 3 +- netwerk/protocol/http/nsHttpChannel.cpp | 4 +- netwerk/protocol/http/nsHttpConnectionMgr.cpp | 2 +- .../components/commandlines/nsCommandLine.cpp | 4 +- .../ApplicationReputation.cpp | 18 ++++--- .../nsUrlClassifierPrefixSet.cpp | 2 +- widget/cocoa/nsCocoaUtils.mm | 3 +- widget/gtk/WindowSurfaceWayland.cpp | 11 ++-- xpcom/base/nsMemoryReporterManager.cpp | 5 +- xpcom/ds/nsExpirationTracker.h | 11 ++-- xpcom/ds/nsTPriorityQueue.h | 50 +++++++++++-------- xpcom/tests/gtest/TestPriorityQueue.cpp | 4 +- 49 files changed, 214 insertions(+), 125 deletions(-) diff --git a/dom/base/CustomElementRegistry.cpp b/dom/base/CustomElementRegistry.cpp index 02c18e339f18..1e112d2047ed 100644 --- a/dom/base/CustomElementRegistry.cpp +++ b/dom/base/CustomElementRegistry.cpp @@ -241,23 +241,19 @@ class MOZ_RAII AutoConstructionStackEntry final { : mStack(aStack) { MOZ_ASSERT(aElement->IsHTMLElement() || aElement->IsXULElement()); -#ifdef DEBUG mIndex = mStack.Length(); -#endif mStack.AppendElement(aElement); } ~AutoConstructionStackEntry() { MOZ_ASSERT(mIndex == mStack.Length() - 1, "Removed element should be the last element"); - mStack.RemoveLastElement(); + mStack.RemoveElementAt(mIndex); } private: nsTArray>& mStack; -#ifdef DEBUG uint32_t mIndex; -#endif }; } // namespace @@ -1299,7 +1295,7 @@ void CustomElementReactionsStack::PopAndInvokeElementQueue() { lastIndex == mReactionsStack.Length() - 1, "reactions created by InvokeReactions() should be consumed and removed"); - mReactionsStack.RemoveLastElement(); + mReactionsStack.RemoveElementAt(lastIndex); mIsElementQueuePushedForCurrentRecursionDepth = false; } diff --git a/dom/base/ResponsiveImageSelector.cpp b/dom/base/ResponsiveImageSelector.cpp index c991c606df48..9536054c5c35 100644 --- a/dom/base/ResponsiveImageSelector.cpp +++ b/dom/base/ResponsiveImageSelector.cpp @@ -204,7 +204,7 @@ void ResponsiveImageSelector::SetDefaultSource(const nsAString& aURLString, int32_t candidates = mCandidates.Length(); if (candidates && (mCandidates[candidates - 1].Type() == ResponsiveImageCandidate::eCandidateType_Default)) { - mCandidates.RemoveLastElement(); + mCandidates.RemoveElementAt(candidates - 1); } mDefaultSourceURL = aURLString; diff --git a/dom/base/nsDOMMutationObserver.cpp b/dom/base/nsDOMMutationObserver.cpp index 04b9f8c7d911..52a935282ed0 100644 --- a/dom/base/nsDOMMutationObserver.cpp +++ b/dom/base/nsDOMMutationObserver.cpp @@ -911,15 +911,16 @@ void nsDOMMutationObserver::EnterMutationHandling() { ++sMutationLevel; } void nsDOMMutationObserver::LeaveMutationHandling() { if (sCurrentlyHandlingObservers && sCurrentlyHandlingObservers->Length() == sMutationLevel) { - nsTArray> obs = - sCurrentlyHandlingObservers->PopLastElement(); + nsTArray>& obs = + sCurrentlyHandlingObservers->ElementAt(sMutationLevel - 1); for (uint32_t i = 0; i < obs.Length(); ++i) { nsDOMMutationObserver* o = static_cast(obs[i]); if (o->mCurrentMutations.Length() == sMutationLevel) { // It is already in pending mutations. - o->mCurrentMutations.RemoveLastElement(); + o->mCurrentMutations.RemoveElementAt(sMutationLevel - 1); } } + sCurrentlyHandlingObservers->RemoveElementAt(sMutationLevel - 1); } --sMutationLevel; } diff --git a/dom/base/nsPlainTextSerializer.cpp b/dom/base/nsPlainTextSerializer.cpp index 7751846f1930..11fb69728d01 100644 --- a/dom/base/nsPlainTextSerializer.cpp +++ b/dom/base/nsPlainTextSerializer.cpp @@ -383,7 +383,13 @@ void nsPlainTextSerializer::PushBool(nsTArray& aStack, bool aValue) { } bool nsPlainTextSerializer::PopBool(nsTArray& aStack) { - return aStack.Length() ? aStack.PopLastElement() : false; + bool returnValue = false; + uint32_t size = aStack.Length(); + if (size > 0) { + returnValue = aStack.ElementAt(size - 1); + aStack.RemoveElementAt(size - 1); + } + return returnValue; } bool nsPlainTextSerializer::IsIgnorableRubyAnnotation( diff --git a/dom/base/nsXMLContentSerializer.cpp b/dom/base/nsXMLContentSerializer.cpp index 6d79fcc66d60..e4f0839cbdd9 100644 --- a/dom/base/nsXMLContentSerializer.cpp +++ b/dom/base/nsXMLContentSerializer.cpp @@ -432,7 +432,7 @@ void nsXMLContentSerializer::PopNameSpaceDeclsFor(nsIContent* aOwner) { if (mNameSpaceStack[index].mOwner != aOwner) { break; } - mNameSpaceStack.RemoveLastElement(); + mNameSpaceStack.RemoveElementAt(index); } } diff --git a/dom/cache/AutoUtils.cpp b/dom/cache/AutoUtils.cpp index 8d55f30420fe..e4d54af4051f 100644 --- a/dom/cache/AutoUtils.cpp +++ b/dom/cache/AutoUtils.cpp @@ -306,7 +306,8 @@ void AutoChildOpArgs::Add(JSContext* aCx, const InternalRequest& aRequest, if (aRv.Failed()) { CleanupChild(pair.request().body(), Delete); - args.requestResponseList().RemoveLastElement(); + args.requestResponseList().RemoveElementAt( + args.requestResponseList().Length() - 1); } break; diff --git a/dom/console/Console.cpp b/dom/console/Console.cpp index 32250522b27c..a2edd7f8f694 100644 --- a/dom/console/Console.cpp +++ b/dom/console/Console.cpp @@ -1935,7 +1935,7 @@ static bool ProcessArguments(JSContext* aCx, const Sequence& aData, // If there isn't any output but there's already a style, then // discard the previous style and use the next one instead. if (output.IsEmpty() && !aStyles.IsEmpty()) { - aStyles.RemoveLastElement(); + aStyles.TruncateLength(aStyles.Length() - 1); } if (NS_WARN_IF(!FlushOutput(aCx, aSequence, output))) { @@ -2084,7 +2084,9 @@ static bool UnstoreGroupName(nsAString& aName, return false; } - aName = aGroupStack->PopLastElement(); + uint32_t pos = aGroupStack->Length() - 1; + aName = (*aGroupStack)[pos]; + aGroupStack->RemoveElementAt(pos); return true; } diff --git a/dom/events/EventDispatcher.cpp b/dom/events/EventDispatcher.cpp index 6a2c59135e3d..c25bff12310d 100644 --- a/dom/events/EventDispatcher.cpp +++ b/dom/events/EventDispatcher.cpp @@ -149,8 +149,9 @@ class EventTargetChainItem { static void DestroyLast(nsTArray& aChain, EventTargetChainItem* aItem) { - MOZ_ASSERT(&aChain.LastElement() == aItem); - aChain.RemoveLastElement(); + uint32_t lastIndex = aChain.Length() - 1; + MOZ_ASSERT(&aChain[lastIndex] == aItem); + aChain.RemoveElementAt(lastIndex); } static EventTargetChainItem* GetFirstCanHandleEventTarget( diff --git a/dom/html/TextControlState.cpp b/dom/html/TextControlState.cpp index 8b564e54cb76..216e545cf3d2 100644 --- a/dom/html/TextControlState.cpp +++ b/dom/html/TextControlState.cpp @@ -1389,7 +1389,8 @@ TextControlState::TextControlState(TextControlElement* aOwningElement) TextControlState* TextControlState::Construct( TextControlElement* aOwningElement) { if (sReleasedInstances && !sReleasedInstances->IsEmpty()) { - TextControlState* state = sReleasedInstances->PopLastElement(); + TextControlState* state = sReleasedInstances->LastElement(); + sReleasedInstances->RemoveLastElement(); state->mTextCtrlElement = aOwningElement; state->mBoundFrame = nullptr; state->mSelectionProperties = SelectionProperties(); diff --git a/dom/html/nsHTMLContentSink.cpp b/dom/html/nsHTMLContentSink.cpp index 8696f1038961..5eb852fd472f 100644 --- a/dom/html/nsHTMLContentSink.cpp +++ b/dom/html/nsHTMLContentSink.cpp @@ -551,13 +551,15 @@ HTMLContentSink::~HTMLContentSink() { mNotificationTimer->Cancel(); } - if (mCurrentContext == mHeadContext && !mContextStack.IsEmpty()) { + int32_t numContexts = mContextStack.Length(); + + if (mCurrentContext == mHeadContext && numContexts > 0) { // Pop off the second html context if it's not done earlier - mContextStack.RemoveLastElement(); + mContextStack.RemoveElementAt(--numContexts); } - for (int32_t i = 0, numContexts = mContextStack.Length(); i < numContexts; - i++) { + int32_t i; + for (i = 0; i < numContexts; i++) { SinkContext* sc = mContextStack.ElementAt(i); if (sc) { sc->End(); @@ -714,8 +716,11 @@ HTMLContentSink::SetParser(nsParserBase* aParser) { nsresult HTMLContentSink::CloseHTML() { if (mHeadContext) { if (mCurrentContext == mHeadContext) { + uint32_t numContexts = mContextStack.Length(); + // Pop off the second html context if it's not done earlier - mCurrentContext = mContextStack.PopLastElement(); + mCurrentContext = mContextStack.ElementAt(--numContexts); + mContextStack.RemoveElementAt(numContexts); } mHeadContext->End(); @@ -837,7 +842,9 @@ void HTMLContentSink::CloseHeadContext() { } if (!mContextStack.IsEmpty()) { - mCurrentContext = mContextStack.PopLastElement(); + uint32_t n = mContextStack.Length() - 1; + mCurrentContext = mContextStack.ElementAt(n); + mContextStack.RemoveElementAt(n); } } diff --git a/dom/indexedDB/ActorsParent.cpp b/dom/indexedDB/ActorsParent.cpp index c5b3a43527d1..2a14e2bec3a4 100644 --- a/dom/indexedDB/ActorsParent.cpp +++ b/dom/indexedDB/ActorsParent.cpp @@ -12496,8 +12496,11 @@ bool ConnectionPool::ScheduleTransaction(TransactionInfo* aTransactionInfo, return false; } } else { - dbInfo->mThreadInfo = - std::move(mIdleThreads.PopLastElement().mThreadInfo); + const uint32_t lastIndex = mIdleThreads.Length() - 1; + + dbInfo->mThreadInfo = std::move(mIdleThreads[lastIndex].mThreadInfo); + + mIdleThreads.RemoveElementAt(lastIndex); AdjustIdleTimer(); } diff --git a/dom/media/platforms/agnostic/DummyMediaDataDecoder.cpp b/dom/media/platforms/agnostic/DummyMediaDataDecoder.cpp index f73c5b3bc3ef..158122e95a86 100644 --- a/dom/media/platforms/agnostic/DummyMediaDataDecoder.cpp +++ b/dom/media/platforms/agnostic/DummyMediaDataDecoder.cpp @@ -43,11 +43,11 @@ RefPtr DummyMediaDataDecoder::Decode( } // Frames come out in DTS order but we need to output them in PTS order. - mReorderQueue.Push(std::move(data)); + mReorderQueue.Push(data); if (mReorderQueue.Length() > mMaxRefFrames) { - return DecodePromise::CreateAndResolve(DecodedData{mReorderQueue.Pop()}, - __func__); + return DecodePromise::CreateAndResolve( + DecodedData{mReorderQueue.Pop().get()}, __func__); } return DecodePromise::CreateAndResolve(DecodedData(), __func__); } @@ -55,7 +55,7 @@ RefPtr DummyMediaDataDecoder::Decode( RefPtr DummyMediaDataDecoder::Drain() { DecodedData samples; while (!mReorderQueue.IsEmpty()) { - samples.AppendElement(mReorderQueue.Pop()); + samples.AppendElement(mReorderQueue.Pop().get()); } return DecodePromise::CreateAndResolve(std::move(samples), __func__); } diff --git a/dom/media/platforms/apple/AppleVTDecoder.cpp b/dom/media/platforms/apple/AppleVTDecoder.cpp index 9b679e90f7bd..067f84d930fb 100644 --- a/dom/media/platforms/apple/AppleVTDecoder.cpp +++ b/dom/media/platforms/apple/AppleVTDecoder.cpp @@ -446,7 +446,7 @@ void AppleVTDecoder::OutputFrame(CVPixelBufferRef aImage, // Frames come out in DTS order but we need to output them // in composition order. MonitorAutoLock mon(mMonitor); - mReorderQueue.Push(std::move(data)); + mReorderQueue.Push(data); MaybeResolveBufferedFrames(); LOG("%llu decoded frames queued", diff --git a/dom/media/webaudio/AudioNode.cpp b/dom/media/webaudio/AudioNode.cpp index 4bc48b5df5cf..7214523d236f 100644 --- a/dom/media/webaudio/AudioNode.cpp +++ b/dom/media/webaudio/AudioNode.cpp @@ -161,12 +161,16 @@ void AudioNode::DisconnectFromGraph() { // Disconnect inputs. We don't need them anymore. while (!mInputNodes.IsEmpty()) { - InputNode inputNode = mInputNodes.PopLastElement(); - inputNode.mInputNode->mOutputNodes.RemoveElement(this); + size_t i = mInputNodes.Length() - 1; + RefPtr input = mInputNodes[i].mInputNode; + mInputNodes.RemoveElementAt(i); + input->mOutputNodes.RemoveElement(this); } while (!mOutputNodes.IsEmpty()) { - RefPtr output = mOutputNodes.PopLastElement(); + size_t i = mOutputNodes.Length() - 1; + RefPtr output = std::move(mOutputNodes[i]); + mOutputNodes.RemoveElementAt(i); size_t inputIndex = FindIndexOfNode(output->mInputNodes, this); // It doesn't matter which one we remove, since we're going to remove all // entries for this node anyway. @@ -176,7 +180,9 @@ void AudioNode::DisconnectFromGraph() { } while (!mOutputParams.IsEmpty()) { - RefPtr output = mOutputParams.PopLastElement(); + size_t i = mOutputParams.Length() - 1; + RefPtr output = std::move(mOutputParams[i]); + mOutputParams.RemoveElementAt(i); size_t inputIndex = FindIndexOfNode(output->InputNodes(), this); // It doesn't matter which one we remove, since we're going to remove all // entries for this node anyway. diff --git a/dom/media/webaudio/AudioNode.h b/dom/media/webaudio/AudioNode.h index deceff805362..3cb05ba522c6 100644 --- a/dom/media/webaudio/AudioNode.h +++ b/dom/media/webaudio/AudioNode.h @@ -143,10 +143,6 @@ class AudioNode : public DOMEventTargetHelper, public nsSupportsWeakReference { } struct InputNode final { - InputNode() = default; - InputNode(const InputNode&) = delete; - InputNode(InputNode&&) = default; - ~InputNode() { if (mTrackPort) { mTrackPort->Destroy(); diff --git a/dom/media/webaudio/AudioParam.cpp b/dom/media/webaudio/AudioParam.cpp index 54b3b8c8a003..69d1d3aea67e 100644 --- a/dom/media/webaudio/AudioParam.cpp +++ b/dom/media/webaudio/AudioParam.cpp @@ -55,7 +55,9 @@ void AudioParam::DisconnectFromGraphAndDestroyTrack() { "mRefCnt.stabilizeForDeletion()"); while (!mInputNodes.IsEmpty()) { - RefPtr input = mInputNodes.PopLastElement().mInputNode; + uint32_t i = mInputNodes.Length() - 1; + RefPtr input = mInputNodes[i].mInputNode; + mInputNodes.RemoveElementAt(i); input->RemoveOutputParam(this); } diff --git a/dom/plugins/base/nsNPAPIPluginInstance.cpp b/dom/plugins/base/nsNPAPIPluginInstance.cpp index 5f1e9baddd07..530f070a8484 100644 --- a/dom/plugins/base/nsNPAPIPluginInstance.cpp +++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp @@ -781,7 +781,9 @@ nsresult nsNPAPIPluginInstance::PushPopupsEnabledState(bool aEnabled) { } nsresult nsNPAPIPluginInstance::PopPopupsEnabledState() { - if (mPopupStates.IsEmpty()) { + int32_t last = mPopupStates.Length() - 1; + + if (last < 0) { // Nothing to pop. return NS_OK; } @@ -789,7 +791,11 @@ nsresult nsNPAPIPluginInstance::PopPopupsEnabledState() { nsCOMPtr window = GetDOMWindow(); if (!window) return NS_ERROR_FAILURE; - PopupBlocker::PopPopupControlState(mPopupStates.PopLastElement()); + PopupBlocker::PopupControlState& oldState = mPopupStates[last]; + + PopupBlocker::PopPopupControlState(oldState); + + mPopupStates.RemoveElementAt(last); return NS_OK; } diff --git a/dom/plugins/ipc/PluginModuleChild.cpp b/dom/plugins/ipc/PluginModuleChild.cpp index a0db99791038..58111414173e 100644 --- a/dom/plugins/ipc/PluginModuleChild.cpp +++ b/dom/plugins/ipc/PluginModuleChild.cpp @@ -1818,14 +1818,13 @@ void PluginModuleChild::EnteredCall() { mIncallPumpingStack.AppendElement(); } void PluginModuleChild::ExitedCall() { NS_ASSERTION(mIncallPumpingStack.Length(), "mismatched entered/exited"); - const IncallFrame& f = mIncallPumpingStack.LastElement(); + uint32_t len = mIncallPumpingStack.Length(); + const IncallFrame& f = mIncallPumpingStack[len - 1]; if (f._spinning) MessageLoop::current()->SetNestableTasksAllowed( f._savedNestableTasksAllowed); - // XXX Is RemoveLastElement intentionally called only after calling - // SetNestableTasksAllowed? Otherwise, PopLastElement could be used above. - mIncallPumpingStack.RemoveLastElement(); + mIncallPumpingStack.TruncateLength(len - 1); } LRESULT CALLBACK PluginModuleChild::CallWindowProcHook(int nCode, WPARAM wParam, diff --git a/dom/smil/SMILTimeContainer.cpp b/dom/smil/SMILTimeContainer.cpp index cc2101cd6b45..55135b349199 100644 --- a/dom/smil/SMILTimeContainer.cpp +++ b/dom/smil/SMILTimeContainer.cpp @@ -185,7 +185,7 @@ nsresult SMILTimeContainer::SetParent(SMILTimeContainer* aParent) { return rv; } -void SMILTimeContainer::AddMilestone( +bool SMILTimeContainer::AddMilestone( const SMILMilestone& aMilestone, mozilla::dom::SVGAnimationElement& aElement) { // We record the milestone time and store it along with the element but this @@ -193,7 +193,7 @@ void SMILTimeContainer::AddMilestone( // between samples). If this happens, then we may do an unecessary sample // but that's pretty cheap. MOZ_ASSERT(!mHoldingEntries); - mMilestoneEntries.Push(MilestoneEntry(aMilestone, aElement)); + return mMilestoneEntries.Push(MilestoneEntry(aMilestone, aElement)); } void SMILTimeContainer::ClearMilestones() { diff --git a/dom/smil/SMILTimeContainer.h b/dom/smil/SMILTimeContainer.h index 6b50a0befb71..b3fb9dd8bcc3 100644 --- a/dom/smil/SMILTimeContainer.h +++ b/dom/smil/SMILTimeContainer.h @@ -168,8 +168,9 @@ class SMILTimeContainer { * @param aMilestone The milestone to register in container time. * @param aElement The timebase element that needs a sample at * aMilestone. + * @return true if the element was successfully added, false otherwise. */ - void AddMilestone(const SMILMilestone& aMilestone, + bool AddMilestone(const SMILMilestone& aMilestone, mozilla::dom::SVGAnimationElement& aElement); /* diff --git a/dom/webbrowserpersist/nsWebBrowserPersist.cpp b/dom/webbrowserpersist/nsWebBrowserPersist.cpp index 1613095bf27e..259415767608 100644 --- a/dom/webbrowserpersist/nsWebBrowserPersist.cpp +++ b/dom/webbrowserpersist/nsWebBrowserPersist.cpp @@ -1696,7 +1696,9 @@ void nsWebBrowserPersist::FinishSaveDocumentInternal(nsIURI* aFile, } if (mWalkStack.Length() > 0) { - mozilla::UniquePtr toWalk = mWalkStack.PopLastElement(); + mozilla::UniquePtr toWalk; + mWalkStack.LastElement().swap(toWalk); + mWalkStack.TruncateLength(mWalkStack.Length() - 1); // Bounce this off the event loop to avoid stack overflow. typedef StoreCopyPassByRRef WalkStorage; auto saveMethod = &nsWebBrowserPersist::SaveDocumentDeferred; diff --git a/dom/workers/Queue.h b/dom/workers/Queue.h index c2ab6aa28a8b..7b39eb9be1db 100644 --- a/dom/workers/Queue.h +++ b/dom/workers/Queue.h @@ -49,7 +49,9 @@ struct StorageWithTArray { return false; } - aEntry = aStorage.PopLastElement(); + uint32_t index = aStorage.Length() - 1; + aEntry = aStorage.ElementAt(index); + aStorage.RemoveElementAt(index); return true; } diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp index ae60068da62f..b6ff321e0719 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -1358,7 +1358,7 @@ bool RuntimeService::ScheduleWorker(WorkerPrivate& aWorkerPrivate) { { MutexAutoLock lock(mMutex); if (!mIdleThreadArray.IsEmpty()) { - thread = std::move(mIdleThreadArray.PopLastElement().mThread); + thread = mIdleThreadArray.PopLastElement().mThread; } } diff --git a/dom/xml/nsXMLContentSink.cpp b/dom/xml/nsXMLContentSink.cpp index db32a6e79dca..1af5b2d3c33d 100644 --- a/dom/xml/nsXMLContentSink.cpp +++ b/dom/xml/nsXMLContentSink.cpp @@ -798,12 +798,14 @@ nsresult nsXMLContentSink::PushContent(nsIContent* aContent) { } void nsXMLContentSink::PopContent() { - if (mContentStack.IsEmpty()) { + int32_t count = mContentStack.Length(); + + if (count == 0) { NS_WARNING("Popping empty stack"); return; } - mContentStack.RemoveLastElement(); + mContentStack.RemoveElementAt(count - 1); } bool nsXMLContentSink::HaveNotifiedForCurrentContent() const { diff --git a/dom/xslt/base/txStack.h b/dom/xslt/base/txStack.h index 83c91ae49d15..310457e8cd78 100644 --- a/dom/xslt/base/txStack.h +++ b/dom/xslt/base/txStack.h @@ -44,7 +44,9 @@ class txStack : private nsTArray { void* object = nullptr; NS_ASSERTION(!isEmpty(), "popping from empty stack"); if (!isEmpty()) { - object = PopLastElement(); + const uint32_t count = Length() - 1; + object = ElementAt(count); + RemoveElementAt(count); } return object; } diff --git a/dom/xslt/xslt/txExecutionState.cpp b/dom/xslt/xslt/txExecutionState.cpp index a4e7609dfc39..60dc42e415a9 100644 --- a/dom/xslt/xslt/txExecutionState.cpp +++ b/dom/xslt/xslt/txExecutionState.cpp @@ -331,8 +331,13 @@ nsresult txExecutionState::pushBool(bool aBool) { bool txExecutionState::popBool() { NS_ASSERTION(mBoolStack.Length(), "popping from empty stack"); + uint32_t last = mBoolStack.Length() - 1; + NS_ENSURE_TRUE(last != (uint32_t)-1, false); - return mBoolStack.IsEmpty() ? false : mBoolStack.PopLastElement(); + bool res = mBoolStack.ElementAt(last); + mBoolStack.RemoveElementAt(last); + + return res; } nsresult txExecutionState::pushResultHandler(txAXMLEventHandler* aHandler) { diff --git a/dom/xslt/xslt/txStylesheetCompiler.cpp b/dom/xslt/xslt/txStylesheetCompiler.cpp index b8819849b39e..2255f75cabb2 100644 --- a/dom/xslt/xslt/txStylesheetCompiler.cpp +++ b/dom/xslt/xslt/txStylesheetCompiler.cpp @@ -589,11 +589,13 @@ nsresult txStylesheetCompilerState::pushPtr(void* aPtr, enumStackType aType) { } void* txStylesheetCompilerState::popPtr(enumStackType aType) { - if (mTypeStack.IsEmpty()) { + uint32_t stacklen = mTypeStack.Length(); + if (stacklen == 0) { MOZ_CRASH("Attempt to pop when type stack is empty"); } - enumStackType type = mTypeStack.PopLastElement(); + enumStackType type = mTypeStack.ElementAt(stacklen - 1); + mTypeStack.RemoveElementAt(stacklen - 1); void* value = mOtherStack.pop(); #ifdef TX_DEBUG_STACK diff --git a/editor/libeditor/TypeInState.cpp b/editor/libeditor/TypeInState.cpp index 5dbab79689a3..d7360b7f6244 100644 --- a/editor/libeditor/TypeInState.cpp +++ b/editor/libeditor/TypeInState.cpp @@ -207,9 +207,15 @@ void TypeInState::ClearProp(nsAtom* aProp, nsAtom* aAttr) { * Caller assumes ownership of PropItem and must delete it. */ UniquePtr TypeInState::TakeClearProperty() { - return mClearedArray.Length() - ? UniquePtr{mClearedArray.PopLastElement()} - : nullptr; + size_t count = mClearedArray.Length(); + if (!count) { + return nullptr; + } + + --count; // indices are zero based + PropItem* propItem = mClearedArray[count]; + mClearedArray.RemoveElementAt(count); + return UniquePtr(propItem); } /** @@ -217,8 +223,14 @@ UniquePtr TypeInState::TakeClearProperty() { * Caller assumes ownership of PropItem and must delete it. */ UniquePtr TypeInState::TakeSetProperty() { - return mSetArray.Length() ? UniquePtr{mSetArray.PopLastElement()} - : nullptr; + size_t count = mSetArray.Length(); + if (!count) { + return nullptr; + } + count--; // indices are zero based + PropItem* propItem = mSetArray[count]; + mSetArray.RemoveElementAt(count); + return UniquePtr(propItem); } /** diff --git a/gfx/layers/ImageContainer.cpp b/gfx/layers/ImageContainer.cpp index dd5660a9ca78..70e6735298ca 100644 --- a/gfx/layers/ImageContainer.cpp +++ b/gfx/layers/ImageContainer.cpp @@ -84,7 +84,10 @@ UniquePtr BufferRecycleBin::GetBuffer(uint32_t aSize) { return UniquePtr(new (fallible) uint8_t[aSize]); } - return mRecycledBuffers.PopLastElement(); + uint32_t last = mRecycledBuffers.Length() - 1; + UniquePtr result = std::move(mRecycledBuffers[last]); + mRecycledBuffers.RemoveElementAt(last); + return result; } void BufferRecycleBin::ClearRecycledBuffers() { diff --git a/gfx/layers/LayerSorter.cpp b/gfx/layers/LayerSorter.cpp index 65b5264dac41..7e9b985ef78a 100644 --- a/gfx/layers/LayerSorter.cpp +++ b/gfx/layers/LayerSorter.cpp @@ -301,9 +301,12 @@ void SortLayersBy3DZOrder(nsTArray& aLayers) { // and remove edges from it. do { if (!noIncoming.IsEmpty()) { - Layer* layer = noIncoming.PopLastElement(); + uint32_t last = noIncoming.Length() - 1; + + Layer* layer = noIncoming.ElementAt(last); MOZ_ASSERT(layer); // don't let null layer pointers sneak into sortedList + noIncoming.RemoveElementAt(last); sortedList.AppendElement(layer); nsTArray::Edge> outgoing; diff --git a/gfx/layers/wr/IpcResourceUpdateQueue.cpp b/gfx/layers/wr/IpcResourceUpdateQueue.cpp index a8a9a393959b..add597470a4f 100644 --- a/gfx/layers/wr/IpcResourceUpdateQueue.cpp +++ b/gfx/layers/wr/IpcResourceUpdateQueue.cpp @@ -72,9 +72,11 @@ layers::OffsetRange ShmSegmentsWriter::Write(Range aBytes) { if (!AllocChunk()) { // Allocation failed, so roll back to the state at the start of this // Write() call and abort. - while (mSmallAllocs.Length() > currAllocLen) { - RefCountedShmem shm = mSmallAllocs.PopLastElement(); + for (size_t i = mSmallAllocs.Length(); currAllocLen < i; i--) { + MOZ_ASSERT(i > 0); + RefCountedShmem& shm = mSmallAllocs.ElementAt(i - 1); RefCountedShm::Dealloc(mShmAllocator, shm); + mSmallAllocs.RemoveElementAt(i - 1); } MOZ_ASSERT(mSmallAllocs.Length() == currAllocLen); return layers::OffsetRange(0, start, 0); diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp index eacc5dce8abf..0863183f96c3 100644 --- a/layout/base/PresShell.cpp +++ b/layout/base/PresShell.cpp @@ -607,10 +607,11 @@ void PresShell::DirtyRootsList::Remove(nsIFrame* aFrame) { nsIFrame* PresShell::DirtyRootsList::PopShallowestRoot() { // List is sorted in order of decreasing depth, so there are no deeper // frames than the last one. - const FrameAndDepth& lastFAD = mList.PopLastElement(); + const FrameAndDepth& lastFAD = mList.LastElement(); nsIFrame* frame = lastFAD.mFrame; // We don't expect frame to change depths. MOZ_ASSERT(frame->GetDepthInFrameTree() == lastFAD.mDepth); + mList.RemoveLastElement(); return frame; } @@ -5258,7 +5259,8 @@ nscolor PresShell::GetDefaultBackgroundColorToDraw() { BrowsingContext* bc = doc->GetBrowsingContext(); if (bc && bc->IsTop() && !bc->HasOpener() && doc->GetDocumentURI() && NS_IsAboutBlank(doc->GetDocumentURI()) && - doc->PrefersColorScheme(Document::IgnoreRFP::Yes) == StylePrefersColorScheme::Dark) { + doc->PrefersColorScheme(Document::IgnoreRFP::Yes) == + StylePrefersColorScheme::Dark) { // Use --in-content-page-background for prefers-color-scheme: dark. return NS_RGB(0x2A, 0x2A, 0x2E); } diff --git a/layout/base/nsBidiPresUtils.cpp b/layout/base/nsBidiPresUtils.cpp index 5e2e9f9bd621..9c6ed0ac35ef 100644 --- a/layout/base/nsBidiPresUtils.cpp +++ b/layout/base/nsBidiPresUtils.cpp @@ -453,7 +453,7 @@ struct MOZ_STACK_CLASS BidiParagraphData { MOZ_ASSERT(mEmbeddingStack.Length(), "embedding/override underflow"); MOZ_ASSERT(aCh == mEmbeddingStack.LastElement()); AppendPopChar(aCh); - mEmbeddingStack.RemoveLastElement(); + mEmbeddingStack.TruncateLength(mEmbeddingStack.Length() - 1); } void ClearBidiControls() { diff --git a/layout/base/nsPresArena.cpp b/layout/base/nsPresArena.cpp index 20e813d62669..95a229532498 100644 --- a/layout/base/nsPresArena.cpp +++ b/layout/base/nsPresArena.cpp @@ -27,10 +27,12 @@ template nsPresArena::~nsPresArena() { #if defined(MOZ_HAVE_MEM_CHECKS) for (FreeList* entry = mFreeLists; entry != ArrayEnd(mFreeLists); ++entry) { - for (void* result : entry->mEntries) { + nsTArray::index_type len; + while ((len = entry->mEntries.Length())) { + void* result = entry->mEntries.ElementAt(len - 1); + entry->mEntries.RemoveElementAt(len - 1); MOZ_MAKE_MEM_UNDEFINED(result, entry->mEntrySize); } - entry->mEntries.Clear(); } #endif } diff --git a/layout/style/ServoStyleSet.cpp b/layout/style/ServoStyleSet.cpp index 607c01f560a4..f4f8dd4c8a5e 100644 --- a/layout/style/ServoStyleSet.cpp +++ b/layout/style/ServoStyleSet.cpp @@ -981,7 +981,10 @@ bool ServoStyleSet::EnsureUniqueInnerOnCSSSheets() { }); while (!queue.IsEmpty()) { - auto [sheet, owner] = queue.PopLastElement(); + uint32_t idx = queue.Length() - 1; + auto* sheet = queue[idx].first; + SheetOwner owner = queue[idx].second; + queue.RemoveElementAt(idx); // Only call EnsureUniqueInner for complete sheets. If we do call it on // incomplete sheets, we'll cause problems when the sheet is actually diff --git a/layout/svg/SVGTextFrame.cpp b/layout/svg/SVGTextFrame.cpp index 3223a777e8d1..7809a44767ad 100644 --- a/layout/svg/SVGTextFrame.cpp +++ b/layout/svg/SVGTextFrame.cpp @@ -1627,7 +1627,7 @@ nsTextFrame* TextFrameIterator::Next() { mCurrentPosition -= mCurrentFrame->GetPosition(); if (mCurrentFrame->GetContent()->IsSVGElement(nsGkAtoms::textPath)) { // Pop off the frame if this is a . - mTextPathFrames.RemoveLastElement(); + mTextPathFrames.TruncateLength(mTextPathFrames.Length() - 1); } // Pop off the current baseline. PopBaseline(); @@ -1674,7 +1674,7 @@ void TextFrameIterator::PushBaseline(nsIFrame* aNextFrame) { void TextFrameIterator::PopBaseline() { NS_ASSERTION(!mBaselines.IsEmpty(), "popped too many baselines"); - mBaselines.RemoveLastElement(); + mBaselines.TruncateLength(mBaselines.Length() - 1); } // ----------------------------------------------------------------------------- diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp index feeff5ea599b..2c7ce10b8d7f 100644 --- a/layout/tables/nsTableFrame.cpp +++ b/layout/tables/nsTableFrame.cpp @@ -570,7 +570,7 @@ void nsTableFrame::InsertCol(nsTableColFrame& aColFrame, int32_t aColIndex) { nsTableColType lastColType = lastCol->GetColType(); if (eColAnonymousCell == lastColType) { // remove the col from the cache - mColFrames.RemoveLastElement(); + mColFrames.RemoveElementAt(numCacheCols - 1); // remove the col from the synthetic col group nsTableColGroupFrame* lastColGroup = (nsTableColGroupFrame*)mColGroups.LastChild(); diff --git a/netwerk/cache2/CacheIndexIterator.cpp b/netwerk/cache2/CacheIndexIterator.cpp index 274b0bcc0102..0c365c1f8282 100644 --- a/netwerk/cache2/CacheIndexIterator.cpp +++ b/netwerk/cache2/CacheIndexIterator.cpp @@ -36,7 +36,8 @@ nsresult CacheIndexIterator::GetNextHash(SHA1Sum::Hash* aHash) { return mStatus; } - memcpy(aHash, mRecords.PopLastElement()->mHash, sizeof(SHA1Sum::Hash)); + memcpy(aHash, mRecords[mRecords.Length() - 1]->mHash, sizeof(SHA1Sum::Hash)); + mRecords.RemoveLastElement(); return NS_OK; } diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index 410b40dfdedc..d10d54944ee9 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -9035,10 +9035,10 @@ void nsHttpChannel::PushRedirectAsyncFunc(nsContinueRedirectionFunc func) { } void nsHttpChannel::PopRedirectAsyncFunc(nsContinueRedirectionFunc func) { - MOZ_ASSERT(func == mRedirectFuncStack.LastElement(), + MOZ_ASSERT(func == mRedirectFuncStack[mRedirectFuncStack.Length() - 1], "Trying to pop wrong method from redirect async stack!"); - mRedirectFuncStack.RemoveLastElement(); + mRedirectFuncStack.TruncateLength(mRedirectFuncStack.Length() - 1); } //----------------------------------------------------------------------------- diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.cpp b/netwerk/protocol/http/nsHttpConnectionMgr.cpp index a70390c5a84c..dda9032029a1 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp +++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp @@ -728,7 +728,7 @@ HttpConnectionBase* nsHttpConnectionMgr::FindCoalescableConnectionByHashKey( listOfWeakConns->Elements()[j] = listOfWeakConns->Elements()[listLen - 1]; } - listOfWeakConns->RemoveLastElement(); + listOfWeakConns->RemoveElementAt(listLen - 1); MOZ_ASSERT(listOfWeakConns->Length() == listLen - 1); listLen--; continue; // without adjusting iterator diff --git a/toolkit/components/commandlines/nsCommandLine.cpp b/toolkit/components/commandlines/nsCommandLine.cpp index 657ccac57f3a..642f466987ba 100644 --- a/toolkit/components/commandlines/nsCommandLine.cpp +++ b/toolkit/components/commandlines/nsCommandLine.cpp @@ -96,7 +96,9 @@ nsCommandLine::RemoveArguments(int32_t aStart, int32_t aEnd) { NS_ENSURE_ARG_MIN(aStart, 0); NS_ENSURE_ARG_MAX(uint32_t(aEnd) + 1, mArgs.Length()); - mArgs.RemoveElementsAt(mArgs.begin() + aStart, mArgs.begin() + aEnd); + for (int32_t i = aEnd; i >= aStart; --i) { + mArgs.RemoveElementAt(i); + } return NS_OK; } diff --git a/toolkit/components/reputationservice/ApplicationReputation.cpp b/toolkit/components/reputationservice/ApplicationReputation.cpp index a881bd22ae62..9ab8f49a5808 100644 --- a/toolkit/components/reputationservice/ApplicationReputation.cpp +++ b/toolkit/components/reputationservice/ApplicationReputation.cpp @@ -990,10 +990,12 @@ nsresult PendingLookup::LookupNext() { // If a url is in blocklist we should call PendingLookup::OnComplete directly. MOZ_ASSERT(mBlocklistCount == 0); + int index = mAnylistSpecs.Length() - 1; nsCString spec; - if (!mAnylistSpecs.IsEmpty()) { + if (index >= 0) { // Check the source URI only. - spec = mAnylistSpecs.PopLastElement(); + spec = mAnylistSpecs[index]; + mAnylistSpecs.RemoveElementAt(index); RefPtr lookup(new PendingDBLookup(this)); // We don't need to check whitelist if the file is not a binary file. @@ -1002,9 +1004,11 @@ nsresult PendingLookup::LookupNext() { return lookup->LookupSpec(spec, type); } - if (!mBlocklistSpecs.IsEmpty()) { + index = mBlocklistSpecs.Length() - 1; + if (index >= 0) { // Check the referrer and redirect chain. - spec = mBlocklistSpecs.PopLastElement(); + spec = mBlocklistSpecs[index]; + mBlocklistSpecs.RemoveElementAt(index); RefPtr lookup(new PendingDBLookup(this)); return lookup->LookupSpec(spec, LookupType::BlocklistOnly); } @@ -1020,9 +1024,11 @@ nsresult PendingLookup::LookupNext() { MOZ_ASSERT_IF(!mIsBinaryFile, mAllowlistSpecs.Length() == 0); // Only binary signatures remain. - if (!mAllowlistSpecs.IsEmpty()) { - spec = mAllowlistSpecs.PopLastElement(); + index = mAllowlistSpecs.Length() - 1; + if (index >= 0) { + spec = mAllowlistSpecs[index]; LOG(("PendingLookup::LookupNext: checking %s on allowlist", spec.get())); + mAllowlistSpecs.RemoveElementAt(index); RefPtr lookup(new PendingDBLookup(this)); return lookup->LookupSpec(spec, LookupType::AllowlistOnly); } diff --git a/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.cpp b/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.cpp index 333c55407668..010811657de5 100644 --- a/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.cpp +++ b/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.cpp @@ -540,7 +540,7 @@ nsresult nsUrlClassifierPrefixSet::WritePrefixes( totalDeltas += deltaLength; indexStarts.AppendElement(totalDeltas); } - indexStarts.RemoveLastElement(); // we don't use the last element + indexStarts.RemoveElementAt(indexSize); // we don't use the last element MOZ_ASSERT(indexStarts.Length() == indexSize); } diff --git a/widget/cocoa/nsCocoaUtils.mm b/widget/cocoa/nsCocoaUtils.mm index 77a246827cc8..529b31677146 100644 --- a/widget/cocoa/nsCocoaUtils.mm +++ b/widget/cocoa/nsCocoaUtils.mm @@ -1421,7 +1421,8 @@ void nsCocoaUtils::ResolveMediaCapturePromises(bool aGranted, PromiseArray& aPro // Remove each promise from the list and resolve it. while (aPromiseList->Length() > 0) { - RefPtr promise = aPromiseList->PopLastElement(); + RefPtr promise = aPromiseList->LastElement(); + aPromiseList->RemoveLastElement(); // Resolve on main thread nsCOMPtr runnable(NS_NewRunnableFunction( diff --git a/widget/gtk/WindowSurfaceWayland.cpp b/widget/gtk/WindowSurfaceWayland.cpp index bdaab31c7499..8bd072bcd371 100644 --- a/widget/gtk/WindowSurfaceWayland.cpp +++ b/widget/gtk/WindowSurfaceWayland.cpp @@ -969,16 +969,19 @@ void WindowSurfaceWayland::CacheImageSurface( WindowImageSurface surf = WindowImageSurface(mImageSurface, aRegion); if (mDelayedImageCommits.Length()) { - auto lastSurf = mDelayedImageCommits.PopLastElement(); - if (surf.OverlapsSurface(lastSurf)) { + int lastSurf = mDelayedImageCommits.Length() - 1; + if (surf.OverlapsSurface(mDelayedImageCommits[lastSurf])) { #ifdef MOZ_LOGGING { - gfx::IntRect size = - lastSurf.GetUpdateRegion()->GetBounds().ToUnknownRect(); + gfx::IntRect size = mDelayedImageCommits[lastSurf] + .GetUpdateRegion() + ->GetBounds() + .ToUnknownRect(); LOGWAYLAND((" removing [ %d, %d] -> [%d x %d]\n", size.x, size.y, size.width, size.height)); } #endif + mDelayedImageCommits.RemoveElementAt(lastSurf); } } diff --git a/xpcom/base/nsMemoryReporterManager.cpp b/xpcom/base/nsMemoryReporterManager.cpp index a1df6616202f..57152f8c9ada 100644 --- a/xpcom/base/nsMemoryReporterManager.cpp +++ b/xpcom/base/nsMemoryReporterManager.cpp @@ -2046,8 +2046,9 @@ void nsMemoryReporterManager::EndProcessReport(uint32_t aGeneration, while (s->mNumProcessesRunning < s->mConcurrencyLimit && !s->mChildrenPending.IsEmpty()) { // Pop last element from s->mChildrenPending - const RefPtr nextChild = - s->mChildrenPending.PopLastElement(); + RefPtr nextChild; + nextChild.swap(s->mChildrenPending.LastElement()); + s->mChildrenPending.TruncateLength(s->mChildrenPending.Length() - 1); // Start report (if the child is still alive). if (StartChildReport(nextChild, s)) { ++s->mNumProcessesRunning; diff --git a/xpcom/ds/nsExpirationTracker.h b/xpcom/ds/nsExpirationTracker.h index 0906f3c0b825..c82ee1412bd0 100644 --- a/xpcom/ds/nsExpirationTracker.h +++ b/xpcom/ds/nsExpirationTracker.h @@ -189,13 +189,12 @@ class ExpirationTrackerImpl { MOZ_ASSERT(generation.Length() > index && generation[index] == aObj, "Object is lying about its index"); // Move the last object to fill the hole created by removing aObj - T* lastObj = generation.PopLastElement(); - // XXX It looks weird that index might point to the element that was just - // removed. Is that really correct? - if (index < generation.Length()) { - generation[index] = lastObj; - } + uint32_t last = generation.Length() - 1; + T* lastObj = generation[last]; + generation[index] = lastObj; lastObj->GetExpirationState()->mIndexInGeneration = index; + generation.RemoveElementAt(last); + MOZ_ASSERT(generation.Length() == last); state->mGeneration = nsExpirationState::NOT_TRACKED; // We do not check whether we need to stop the timer here. The timer // will check that itself next time it fires. Checking here would not diff --git a/xpcom/ds/nsTPriorityQueue.h b/xpcom/ds/nsTPriorityQueue.h index f1052f9de1de..b5a02957c018 100644 --- a/xpcom/ds/nsTPriorityQueue.h +++ b/xpcom/ds/nsTPriorityQueue.h @@ -32,8 +32,11 @@ class nsTPriorityQueue { */ explicit nsTPriorityQueue(const Compare& aComp) : mCompare(aComp) {} - nsTPriorityQueue(nsTPriorityQueue&&) = default; - nsTPriorityQueue& operator=(nsTPriorityQueue&&) = default; + /** + * Copy constructor + */ + nsTPriorityQueue(const nsTPriorityQueue& aOther) + : mElements(aOther.mElements), mCompare(aOther.mCompare) {} /** * @return True if the queue is empty or false otherwise. @@ -62,8 +65,11 @@ class nsTPriorityQueue { * @param aElement The element to add * @return true on success, false on out of memory. */ - void Push(T&& aElement) { - mElements.AppendElement(std::move(aElement)); + bool Push(const T& aElement) { + T* elem = mElements.AppendElement(aElement); + if (!elem) { + return false; // Out of memory + } // Sift up size_type i = mElements.Length() - 1; @@ -72,9 +78,11 @@ class nsTPriorityQueue { if (mCompare.LessThan(mElements[parent], mElements[i])) { break; } - std::swap(mElements[i], mElements[parent]); + Swap(i, parent); i = parent; } + + return true; } /** @@ -85,34 +93,29 @@ class nsTPriorityQueue { */ T Pop() { MOZ_ASSERT(!mElements.IsEmpty(), "Empty queue"); - T pop = std::move(mElements[0]); - - const size_type newLength = mElements.Length() - 1; - if (newLength == 0) { - mElements.Clear(); - return pop; - } + T pop = mElements[0]; // Move last to front - mElements[0] = mElements.PopLastElement(); + mElements[0] = mElements[mElements.Length() - 1]; + mElements.TruncateLength(mElements.Length() - 1); // Sift down size_type i = 0; - while (2 * i + 1 < newLength) { + while (2 * i + 1 < mElements.Length()) { size_type swap = i; size_type l_child = 2 * i + 1; if (mCompare.LessThan(mElements[l_child], mElements[i])) { swap = l_child; } size_type r_child = l_child + 1; - if (r_child < newLength && + if (r_child < mElements.Length() && mCompare.LessThan(mElements[r_child], mElements[swap])) { swap = r_child; } if (swap == i) { break; } - std::swap(mElements[i], mElements[swap]); + Swap(i, swap); i = swap; } @@ -133,14 +136,17 @@ class nsTPriorityQueue { */ const T* Elements() const { return mElements.Elements(); } - nsTPriorityQueue Clone() const { - auto res = nsTPriorityQueue{mCompare}; - res.mElements = mElements.Clone(); - return res; + protected: + /** + * Swaps the elements at the specified indices. + */ + void Swap(size_type aIndexA, size_type aIndexB) { + T temp = mElements[aIndexA]; + mElements[aIndexA] = mElements[aIndexB]; + mElements[aIndexB] = temp; } - protected: - nsTArray mElements; + CopyableTArray mElements; Compare mCompare; // Comparator object }; diff --git a/xpcom/tests/gtest/TestPriorityQueue.cpp b/xpcom/tests/gtest/TestPriorityQueue.cpp index c5f59072da43..48b78ccf958d 100644 --- a/xpcom/tests/gtest/TestPriorityQueue.cpp +++ b/xpcom/tests/gtest/TestPriorityQueue.cpp @@ -13,7 +13,7 @@ template void CheckPopSequence(const nsTPriorityQueue& aQueue, const T* aExpectedSequence, const uint32_t aSequenceLength) { - nsTPriorityQueue copy = aQueue.Clone(); + nsTPriorityQueue copy(aQueue); for (uint32_t i = 0; i < aSequenceLength; i++) { EXPECT_FALSE(copy.IsEmpty()); @@ -52,7 +52,7 @@ TEST(PriorityQueue, Main) // copy ctor is tested by using CheckPopSequence, but check default assignment // operator nsTPriorityQueue queue2; - queue2 = queue.Clone(); + queue2 = queue; CheckPopSequence(queue2, expected, sizeof(expected) / sizeof(expected[0])); queue.Clear();